在 C++ 中使用字符串数组拆分声明和赋值

Splitting declaration and assignment with string array in C++

可能有一个非常简单的解决方案,但我似乎无法弄清楚。我可以找到无数关于如何在 C++ 中创建字符串数组的示例,但我找不到一个说明如何单独赋值的示例。

我目前有一个看起来像这样的赋值声明:

static const char *desc[3] = { "apple", "banana", "orange" };

我想做的是将声明和赋值拆分为单独的语句。宣言:

static const char *desc[3];

...但我似乎无法弄清楚如何完成作业。我尝试了以下方法:

desc = { "apple", "banana", "orange" }; // Expression must have a modifiable lvalue. error: assigning to an array from an initializer list
*desc = { "apple", "banana", "orange" }; // Too many initializer values. error: cannot convert '<brace-enclosed initializer list>' to 'const char*' in assignment
desc[3] = { "apple", "banana", "orange" }; // Too many initializer values. error: cannot convert '<brace-enclosed initializer list>' to 'const char*' in assignment
*desc[3] = { "apple", "banana", "orange" }; // Expression must have a modifiable lvalue. error: assignment of read-only location '* desc[3]'

您的第一个示例在堆栈上分配数组,这是唯一可能的,因为编译器知道大小(因为所有字符串都是固定长度并在声明期间提供)。

当你将声明和初始化分开时,你的编译器无法知道在堆栈上分配多少内存,所以你需要将你的类型更改为指针(它具有固定大小,无论它指向什么到):

static const char** desc;

然后使用new为数组分配足够的内存:

desc = new const char*[3]{ "apple", "banana", "orange" };

然而,这意味着您现在还必须 delete[] desc 指向的数组,否则会发生内存泄漏。

更好的方法是使用像 std::vectorstd::string 这样的现代容器类型:

static std::vector<std::string> desc;

然后

desc.push_back("apple");
desc.push_back("banana");
desc.push_back("orange");

这些 类 会在后台为您处理所有令人讨厌的内存管理。


另一种选择,如果你真的想要一个原始数组,并且不想依赖 new[]delete[] 是声明一个具有足够 space 的固定大小数组你的字符串是这样的:

static const char desc[3][128];

然后将字符串值复制到该内存块中:

std::strcpy(desc[0], "apple");
std::strcpy(desc[1], "banana");
std::strcpy(desc[2], "orange");

但是我真的不建议这样做,因为当您添加或删除字符串,或更改它们的长度等时,您可能会在长 运行 中遇到错误

您的声明是错误的,因为当您编写 char [3] 时,它会使您的字符数组包含 3 个字符,而不是包含 3 个不同的无限字符的数组。

I currently have a declaration with assignment that looks something like this:

static const char *desc[3] = { "apple", "banana", "orange" };

这不是“作业”。这是初始化。

I can't seem to figure out how to do the assignment.

数组不可赋值。您不能分配给数组。

如果你想在初始化后修改数组的元素,你要么需要遍历每个元素并一一赋值:

const char *arr[] = {"apple", "banana", "orange"};
static_assert(std::size(arr) == std::size(desc));
std::copy_n(arr, std::size(arr), desc);

或者您可以将数组包装成一个class,在这种情况下,将为您生成一个赋值运算符。这种数组包装器有一个标准模板 std::array:

static std::array<const char*, 3> desc;
// later
desc = {"apple", "banana", "orange"};

Max Vollmer 给出了一些很好的建议,尽管在 "modern C++" (post C++11) 中不鼓励使用 new 和原始指针。参见[1](Sutter是C++标准委员会的成员,所以他知道他的事。

所以如果你想要 "true C++ way" 有一个字符串数组,那么你应该去:

std::vector<std::string> dest_a;
dest_a.push_back("apple");
dest_a.push_back("banana");
// or
std::vector<std::string> dest_b(3);
dest_b[0] = "orange";
dest_b[1] = "pear";
dest_b[2] = "plumb";

如果您需要原始指针,我想我会选择旧的 C strcpy 函数。


虽然,您可能只是在寻找这个。

  static const char *ptr[2];
  ptr[0] = "orange";
  ptr[1] = "pear";

[1] https://herbsutter.com/elements-of-modern-c-style/