C++ 无法从成员变量中的初始值设定项字符串推断数组大小的原因是什么?
以代码为例:C++ 无法从成员变量中的初始值设定项字符串推断数组大小的原因是什么?,c++,c++11,c-strings,in-class-initialization,C++,C++11,C Strings,In Class Initialization,以代码为例: struct Foo { const char str[] = "test"; }; int main() { Foo foo; } 它不能同时使用g++和clang++进行编译,从本质上讲,这是一个错误 错误:无法从类内初始值设定项推断数组绑定 我知道这可能是标准所说的,但有什么特别好的理由吗?由于我们有一个字符串文字,编译器似乎应该能够毫无问题地推断大小,类似于简单地声明类外constC类空终止字符串的情况。原因是,您始终可以重写构造函数中的类内初始值设定项
struct Foo
{
const char str[] = "test";
};
int main()
{
Foo foo;
}
它不能同时使用g++和clang++进行编译,从本质上讲,这是一个错误
错误:无法从类内初始值设定项推断数组绑定
我知道这可能是标准所说的,但有什么特别好的理由吗?由于我们有一个字符串文字,编译器似乎应该能够毫无问题地推断大小,类似于简单地声明类外
const
C类空终止字符串的情况。原因是,您始终可以重写构造函数中的类内初始值设定项列表。所以我想最终,这可能会让人非常困惑
struct Foo
{
Foo() {} // str = "test\0";
// Implementing this is easier if I can clearly see how big `str` is,
Foo() : str({'a','b', 'c', 'd'}) {} // str = "abcd0"
const char str[] = "test";
};
请注意,将
const char
替换为static constexpr char
效果很好,这可能正是您想要的。如果允许编译器支持您描述的内容,并且str
的大小被推断为5
Foo foo = {{"This is not a test"}};
将导致未定义的行为。如评论中所述以及@sbabbi的回答,答案在于细节 12.6.2初始化基和成员[class.base.init]
- 如果实体是具有大括号或相等初始值设定项的非静态数据成员,则将按照中的指定初始化该实体 8.5; 李>
- 否则,如果实体是匿名联盟或变体成员(9.5),则不执行初始化李>
- 否则,该实体将默认初始化
struct A {
int i = /∗ some integer expression with side effects ∗/ ;
A(int arg) : i(arg) { }
// ...
};
struct Foo {
int i[5] ={1,2,3,4,5};
int j;
Foo(): j(0) {};
}
相当于
struct Foo {
int i[5];
int j;
Foo(): j(0), i{1,2,3,4,5} {};
}
但是现在我们看到,如果忽略数组大小,表达式将是格式错误的
但是接着说,编译器本可以在成员不是通过成员内构造函数初始化的情况下支持该功能,但目前为了统一起见,该标准与其他许多东西一样,不支持此功能。Related:由于
str
也可以在Foo构造函数的成员初始化列表中初始化,因此从类内初始化器中丢弃初始化器相关问题讨论:@aruistante谢谢,您可以将其标记为dupe,我自己无法找到dupe。虽然只有第一个链接可能是一个复制品,没有被接受的答案。@PiotrS。你应该发布一个答案,因为它现在清楚了!谢谢,有道理。在C++11之前,有没有办法使这项工作正常进行?仅使用static const
不起作用。@有趣的是,这表明如果删除每个用户声明的构造函数,并且隐式生成默认构造函数,则可以允许这种行为。也许值得一提?