如何在优雅的对象中包装 C 样式数组?

How to wrap a C style array in an Elegant Object?

我在 C++98 中使用一个使用 C 风格数组的库。

我想隐藏所有这些并通过声明代码简单地与之交互。 我正在寻找类似这个伪代码的东西。 智能指针是一个挑战。

我可以使用 boost 1.61 的 boost 智能指针 https://www.boost.org/doc/libs/1_61_0/libs/smart_ptr/smart_ptr.htm

class ElegantArray
{
  private:
    char* array;  // <<<==== should be a unique or auto ptr?
    int size;
    std::string aString;

  public:

    ElegantArray(char* array_, int size_) { // <<<=============should require a smart pointer
      array = array_;
      size = size_;    //<<<===constructor leaves aString nil which requires nil checks =(
    }

    ElegantArray(std::string aString_) {
      aString = aString_;   // <<<===constructor leaves array and size nil which requires nil checks =(
    }

  std::string string() {
    int i;  //put inside for loop?
    std::string strng = "";
    for (i = 0; i < size; i++) { strng = strng + array[i]; }
    return strng;
  }

  //How & What do i return here unique or auto ptr?
  char* cArrayPointer() {
    int n = aString.length();
    char charArray[n+1];
    strcpy(charArray, aString.c_str());
    return charArray;  // <<<==================should return a smart pointer
  }    
}

调用站点类似于

ElegantArray elegantArray(smartPointerToCArray, arraySize);
std::string aString = elegantArray.string();

ElegantArray elegantArray("Falalalala");
SmartPointerToCArray smartPointerToCArray = elegantArray.cArrayPointer();

请指教

我猜你说的是 char 的 c 数组。在这种情况下,您正在寻找 std::string:

#include <string>
#include <iostream>
int main() {
    typedef std::string ElegantArray;

    char x[] = "Foo";
    const char* y = "Bar";

    ElegantArray a(x);
    ElegantArray b(y);
    ElegantArray c("Baz");
    std::cout << a << " " << b << " " << c;

}

如果您需要 c 字符串,请使用 std::string::c_str()

我假设您正在使用处理 char * 的 API;需要与处理 std::string 的其他 API 交互,或者只是想在您自己的代码中使用更好的表示形式。无论哪种情况,std::string 本身都可能是理想的解决方案。

std::string 类型已经支持两种类型之间的转换;例如:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <iostream>
#include <string>

void print_c_string(const char *arr)
{
    printf("arr := '%s'\r\n", arr);
}

void print_std_string(std::string str)
{
    std::cout << "str := '" << str << '\'' << std::endl;
}

int main(int argc, char *argv[])
{
    // Get a C-style string
    char *arr = (char *)malloc(strlen("c-style string") + 1);
    memcpy(arr, "c-style string", strlen("c-style string"));
    arr[strlen("c-style string")] = '[=10=]';

    // Get a std::string
    std::string str("standard lib string");

    print_c_string(arr);
    print_std_string(str);

    // Get a std::string from the C-style string
    std::string fromArr(arr);
    print_std_string(fromArr);

    // Get C-style string from std::string
    print_c_string(str.c_str());

    free(arr);
    return 0;
}

// output:
// arr := 'c-style string'
// str := 'standard lib string'
// str := 'c-style string'
// arr := 'standard lib string'

就生命周期而言,从 char * 构建 std::string 将复制数据,因此生命周期不会耦合。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <iostream>
#include <string>

int main(int argc, char *argv[])
{
    // Get a C-style string
    char *arr = (char *)malloc(strlen("c-style string") + 1);
    memcpy(arr, "c-style string", strlen("c-style string"));
    arr[strlen("c-style string")] = '[=11=]';

    {
        std::string str(arr);
        std::cout << "std::string from arr := '" << str << '\'' << std::endl;
        str.clear();
        std::cout << "cleared std::string from arr := '" << str << '\'' << std::endl;
    }

    printf("arr := '%s'\r\n", arr);

    free(arr);
    return 0;
}

// output:
// std::string from arr := 'c-style string'
// cleared std::string from arr := ''
// arr := 'c-style string'

另一方面,从 std::string 获取 char * 实际上会给出一个指向字符串数据的指针,因此您需要考虑 [=13= 的消费者如何] 会治疗的

#include <iostream>
#include <string>

int main(int argc, char *argv[])
{
    const char *arr;

    {
        std::string str("standard lib string");

        arr = str.c_str();
        printf("arr := '%s'\r\n", arr);

        // Modifying the data at the char * will affect the string, don't do this.
        //
        // http://www.cplusplus.com/reference/string/string/c_str/
        // > A program shall not alter any of the characters in this sequence.
        ((char *)arr)[1] = '7';
        std::cout << "str := '" << str << '\'' << std::endl;

        // The implication here is that if an API is expecting a char * that it will
        // modify or own then you'll need to copy the data out and manage the lifetime
        // of the copy accordingly.

        // Mutating the string will similarly change the data at the char *.
        for (auto & c: str) c = toupper(c);
        printf("arr := '%s'\r\n", arr);
    }

    // Once the string is gone there's no guarantee about the data at the char *.
    // You'll need to make sure the string outlives the char * or make a copy of the data.

    printf("arr := '%s'\r\n", arr);

    return 0;
}

// output:
// arr := 'standard lib string'
// str := 's7andard lib string'
// arr := 'S7ANDARD LIB STRING'
// arr := ''