为什么我不能在结构体中初始化字符数组

4

我尝试通过以下方式在结构声明中初始化字符数组。但是它无法编译,并显示了错误消息。 请告诉我为什么它无法编译。

#include <iostream>

struct A {
    const char value_in_struct[] = "a";  // this line gives me a error message.
};

void t(void) {
    const char value[] = "a";  // this line was ok at compiling
    std::cout << "value = " << value << std::endl;
}

我从gcc收到了以下错误信息。
../static_constexpr_array.hpp:16:33: error: initializer-string for array of chars is too long [-fpermissive]
  const char value_in_struct[] = "a";
                                 ^

感谢您抽出时间来与我交流。

1
因为这个语法只支持 const char[] - Violet Giraffe
1
类内大括号或等号初始化需要C++11及以上版本。 - Lingxi
1
据我所知,类内初始化器必须位于花括号内和/或在等号后。我猜想这是因为没有指定数组大小,由于编译器需要知道为A对象保留多少空间,但如果此类代码是可能的,则value_in_struct的大小可能会根据其如何初始化(例如复制或默认初始化)而更改。希望有人能引用标准来详细说明此问题。 - Silversonic
谢谢Silversonic。如果我的gcc版本如下,gcc(Ubuntu 5.2.1-22ubuntu2)5.2.1 20151010。再次感谢您。 - mora
@BlackMoses,它无法编译,这就是问题所在。但是当value_in_struct被声明为静态时,它存在于一个大小不变的单个对象中,这就是为什么它可以解决问题的原因。 - Silversonic
显示剩余11条评论
4个回答

4
问题在于无法从类内初始化程序自动推断出数组范围。clang产生的错误信息非常清晰(请参见这里)。
prog.cc:4:34: error: array bound cannot be deduced from an in-class initializer
    const char value_in_struct[] = "a"; 
                                 ^

那么这是为什么呢?因为类内初始化器可以被构造函数的成员初始化列表覆盖。所以,如果一个构造函数选择用其他方式初始化数组会怎样呢?在你的情况下,可以使用花括号包围的初始化器列表来覆盖初始化器(实际上是聚合初始化)(请参见此处):

A a = {"abc"};

由于在编译时无法确定最终的初始化器,编译器无法推断数组范围。

为数组指定一个明确的范围可以使代码编译通过(请参见此处)。

#include <iostream>

struct A {
    const char value_in_struct[2] = "a";  
};

void t(void) {
    char value[] = "a";
    std::cout << "value = " << value << std::endl;
}

@Silversonic 这对于C++11是正确的,但自从C++14以来就不再是了。请参见这里 - Lingxi
@Silversonic 注意语句 *no default member initializers (since C++11) (until C++14)*。 - Lingxi
谢谢Lingxi。对我来说,这是非常清晰明了的回答,非常好。 - mora

1
struct A {
    const char value_in_struct[] = "a";.
};

这是错误的。这是数组类成员还是对象成员?如果它是类成员,你必须这样写:
static constexpr char value_in_struct[] = "a";

它是静态成员,因此使用Static。由于在类定义中初始化,因此使用Constexpr。

如果它是对象成员,则无法在类定义内进行初始化。


这是C++11中引入的类内大括号或等号初始化器。 - Lingxi

1
感谢您提出问题,当您声明const char var[] =“something”;时,它意味着您正在声明类型为char数组的变量var,并将其长度与初始化字符串相同。例如,对于上述情况,它是10。
只有在您可以初始化变量时,即在main函数或任何其他函数中声明它时,语句才会有效。
现在,您的代码结构部分声明了一个struct A,在其中声明了变量或const char [],在这里您无法初始化它,因此会出错。此外,如果您声明具有此类成员变量的结构并尝试创建实例,则会出现编译错误,因为它是const类型,我们需要在创建实例时对其进行初始化,这是不可能的。
解决方法是在结构中将成员变量作为char *类型并相应地进行分配,这样您将能够实现所需的内容。
我尝试了一些相同行的代码,并用注释标出了将导致编译错误的行,请参见,希望能帮到您。
#include <iostream>
using namespace std;

struct B{
    const char mem_var[];
};

struct A {
    const char * value_in_struct ;  // this line gives me a error message.
    A(char *s):value_in_struct(s){}
    A() { value_in_struct = NULL;}
};

void t(void) {
    const char value[] = "att";  // this line was ok at compiling
    std::cout << "value = " << value << std::endl;
    //value[2] = 's';  // gives error
}

int main(){
    A a(const_cast< char *>("abc"));
    A b ;
    b.value_in_struct = "bbc";
    cout <<"a: "<<a.value_in_struct << endl;
    cout <<"b: "<<b.value_in_struct << endl;
    t();
    //B bb; gives error for not initizaling mem_var
    return 0;
}

感谢 rocky_mfe 给了我另一种选择。 - mora

0

我已经有一段时间没有使用C++了,但是我可以建议尝试一下:

const char[] value_in_strict = {'a'};

这应该是一条注释。但我理解你不能这样做,因为你的声望还不够。 - edmz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接