【问题标题】:Why can't I initialize the char array in the structure?为什么我不能初始化结构中的 char 数组?
【发布时间】:2023-04-01 07:56:01
【问题描述】:
typedef struct book {

   int a;
   int b;
   char cb[100];

   book(int a1, int b1, char* cb1) {
       a = a1;
       b = b1;
       cb = cb1;
   }

} book;

为什么我不能将 cb 初始化为 cb1 以及如何在没有 strcpy 的情况下做到这一点?

【问题讨论】:

  • cb 是数组,不是指针,不能赋值。它实际上是在结构内部已经为你分配的内存,你得到了这个地段的关键。就像“在这里,我买了房子,它在 Wayway Ave 39”,而你的妻子说“太好了,你能把它搬到马路对面到 Wayway Ave 40 吗?”如果您想要一个可以分配给的指针,请改为 char *cb

标签: c++ string struct


【解决方案1】:

为什么我不能将 cb 初始化为 cb1 以及如何在没有 strcpy 的情况下做到这一点?

cb1char* 类型,但 cb 是 C 风格的数组,也就是正式的 数组类型的对象(这个具体是 char[100])。 Objects of array type cannot be modified(即使它们是左值)。如果你只想浅拷贝而不是像你说的strcpy(),那么你可以将cb定义为char*而不是char[100]

typedef struct book {

   // ...
   char* cb;

   book(int a1, int b1, char* cb1) {
       // ...
       cb = cb1;
   }

} book;

但在大多数情况下,我不建议这样做,因为它会导致对该原始指针的不稳定管理。这被标记为 [C++],有什么理由不使用 std::string


注意:虽然您没有标记此 [C++11] 或更高版本,但当您尝试使用上述结构时,可能会出现不使用此类原始指针或 C 样式数组的进一步原因像这样:

int main() {
    book b(4, 2, "Hello");
    return 0;
}

诸如 Clang 之类的标准编译器会立即让您知道1

ISO C++11 不允许将字符串文字转换为“char *”。

这种从字符串文字 (the type of which is const char[]) 到char* 的隐式转换即使在C++03 中也已被弃用,现在completely removed since C++11.

1 默认情况下,这至少是一个警告,并且在使用-pedantic-errors 构建时会出现错误。

【讨论】:

  • 有这个测试,我们只能使用iostream。我是 cpp 的初学者,所以所有这些与指针的处理真的让我很困惑。
  • @ManishMadugula 好的朋友没问题。所以你不允许使用`std::string'?您是否希望我在有关使用此指针的答案中添加其他说明?
  • @SkepticalEmpiricist 谢谢你的回答确实澄清了我的疑问。无需进一步解释。
  • @SkepticalEmpiricist:您的程序自 C++11 起无效。
  • @SkepticalEmpiricist 你花了将近 7 个小时来研究。 ;) 并想出了一个很好的答案。值得一去:)
【解决方案2】:

你问为什么不能在struct中初始化char[]

你的问题的答案是因为:

数组是 C 中的“二等公民”;这种偏见的一个结果是你不能分配给他们。在 C 和 C++ 中,数组不是可修改的 lvalue

C 和 C++ 都是不同的编程语言。在 C++ 中应避免使用普通的旧 C 样式数组,因为 C++ 语言提供了方便且更好的替代方案。

因为这个问题已被标记为 C++ 问题,所以惯用的解决方案是在 C++ 中使用 std::string

因此,如果您执行以下操作会更好:

#include <string>

struct book {

   int a;
   int b;
   std::string cb;

   book(int a1, int b1, std::string cb1) {
       a = a1;
       b = b1;
       cb = cb1;
   }

} book;

【讨论】:

  • 我不会说数组是二等公民。数组类型是完全成熟的类型。它们是真实的东西,而不是幽灵。它们具有存储空间、使用寿命以及您所期望的一切。您可以很好地传递指针和对它们的引用,并且(当包装在类中时)也可以复制/移动。就我个人而言,我认为名称衰减规则以及无法通过直接分配进行复制是孤立的怪事。无论如何,没关系,因为 OP 正试图从一个已经有缺陷的指针初始化一个数组。
【解决方案3】:

您的帖子被标记为 [C++],但没有使用现代成语。这是一个允许简单初始化的版本。通过使用std::string,可以避免复杂的初始化。

请注意,您也不必重命名参数。

使用std::string

#include <iostream>
#include <string>

class book {
public:
   int a;
   int b;
   std::string cb;

   book(int a, int b, const char* cb)
    : a(a),
      b(b),
      cb(cb)
    {
    }
};

int main()
{
    using namespace std;
    const book test(5, 17, "Woot!");
    cout << "Hello " << test.cb << endl; 

    return 0;
}

输出

$main
Hello Woot!

【讨论】:

  • 您还可以将cb 参数定义为std::string 类型
  • 对数据成员使用const 不是一个好主意
  • @M.M.你让它听起来像是天生的坏事。
  • 如果您想将其放入容器中,我想您最好使用无法通过提供的 API 修改的可变但私有的成员
  • 好吧好吧^_^
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-07
  • 1970-01-01
  • 2010-09-18
  • 1970-01-01
  • 2014-11-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多