vso*_*tco 17 c++ c-strings in-class-initialization c++11
考虑一下代码:
struct Foo
{
const char str[] = "test";
};
int main()
{
Foo foo;
}
Run Code Online (Sandbox Code Playgroud)
它无法使用g ++和clang ++编译,基本上吐出来
error: array bound cannot be deduced from an in-class initializer
我明白这是标准可能会说的,但有什么特别好的理由吗?由于我们有一个字符串文字,似乎编译器应该能够毫无问题地推断出大小,类似于简单地声明一个类外const的类似C的空终止字符串的情况.
sba*_*bbi 12
原因是您始终可以覆盖构造函数中的类内初始化列表.所以我想最后,它可能会非常混乱.
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";
};
Run Code Online (Sandbox Code Playgroud)
请注意,替换const char为static constexpr char完美的工作,可能它是你想要的.
正如评论中提到的和@sbabbi 所回答的,答案在于细节
12.6.2 初始化基类和成员 [class.base.init]
在非委托构造函数中,如果给定的非静态数据成员或基类未由 mem-initializer-id 指定(包括由于构造函数没有 ctor-initializer 而没有 mem-initializer-list 的情况)并且实体不是抽象类(10.4)的虚拟基类,那么
- 如果实体是一个非静态数据成员,它有一个大括号或等号初始化器,实体按照 8.5 中的规定进行初始化;
- 否则,如果实体是匿名联合或变体成员(9.5),则不执行初始化;
- 否则,实体是默认初始化的
12.6.2 初始化基类和成员 [class.base.init]
如果给定的非静态数据成员同时具有大括号或等号初始化器和内存初始化器,则执行内存初始化器指定的初始化,非静态数据成员的大括号或等号初始化器为忽略。[ 示例:给定
Run Code Online (Sandbox Code Playgroud)struct A { int i = /? some integer expression with side effects ?/ ; A(int arg) : i(arg) { } // ... };A(int) 构造函数将简单地将 i 初始化为 arg 的值,并且不会发生 i 的大括号或相等初始化器中的副作用。— 结束示例 ]
因此,如果存在非删除构造函数,则忽略大括号或相等初始化器,并以构造函数成员内初始化为准。因此,对于省略大小的数组成员,表达式变得不正确。§12.6.2,第 9 项,在我们指定如果内存初始化由构造函数执行时省略 r 值初始化表达式的地方更加明确。
此外,谷歌小组讨论在 C++ 中的另一个不一致的行为,进一步阐述并使其更加清晰。它扩展了解释大括号或相等初始化器是成员内初始化的一种美化方式的想法,用于成员的成员内初始化不存在的情况。举个例子
struct Foo {
int i[5] ={1,2,3,4,5};
int j;
Foo(): j(0) {};
}
Run Code Online (Sandbox Code Playgroud)
相当于
struct Foo {
int i[5];
int j;
Foo(): j(0), i{1,2,3,4,5} {};
}
Run Code Online (Sandbox Code Playgroud)
但是现在我们看到,如果省略数组大小,则表达式将是格式错误的。
但是话虽如此,对于成员未通过成员内构造函数初始化初始化的情况,编译器可能会支持该功能,但目前为了统一起见,与许多其他事物一样,标准不支持此功能。
| 归档时间: |
|
| 查看次数: |
3903 次 |
| 最近记录: |