首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么不能从成员变量中的初始化器-字符串中推断数组大小?

为什么不能从成员变量中的初始化器-字符串中推断数组大小?
EN

Stack Overflow用户
提问于 2015-04-12 18:45:26
回答 3查看 12.8K关注 0票数 22

考虑一下守则:

代码语言:javascript
运行
复制
struct Foo
{
    const char str[] = "test";
};

int main()
{
    Foo foo;
}

它不能同时使用g++和clang++进行编译,本质上是抛出的。

error: array bound cannot be deduced from an in-class initializer

我知道标准可能是这么说的,但有什么特别好的理由吗?因为我们有一个字符串文本,所以编译器似乎应该能够在没有任何问题的情况下推断出字符串的大小,类似于您只需要声明一个类外const C类的空终止字符串时的情况。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-04-12 18:55:59

原因是,您始终有可能重写构造函数中的类内初始化程序列表。所以我想到最后,这可能会很令人困惑。

代码语言:javascript
运行
复制
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非常有效,而且可能无论如何都是您想要的。

票数 20
EN

Stack Overflow用户

发布于 2015-04-12 19:27:41

正如评论中提到的那样,正如@sbabbi所回答的,答案在于细节。

12.6.2初始化基和成员class.base.init

  1. 在非委托构造函数中,如果给定的非静态数据成员或基类不是由mem初始化器id指定的(包括由于构造函数没有ctor初始化器而没有mem初始化程序列表的情况),且实体不是抽象类的虚拟基类(10.4),则
代码语言:javascript
运行
复制
- if the entity is a non-static data member that has a brace-or-equal-initializer , the entity is initialized as specified in   8.5; 
- otherwise, if the entity is an anonymous union or a variant member (9.5), no initialization is performed; 
- otherwise, the entity is default-initialized

12.6.2初始化基和成员class.base.init

  1. 如果给定的非静态数据成员同时具有大括号或等初始化器和mem初始化器,则执行mem初始化程序指定的初始化,忽略非静态数据成员的大括号或等初始化器。[例子:给予 结构A{ int i= /∗具有副作用的整数表达式∗/;A(int arg):i(arg) {} // . };

A(int)构造函数将简单地将I初始化为arg的值,并且I的支撑--或相等--初始化器中的副作用不会发生。-最终例子]

因此,如果存在不删除构造函数,则忽略大括号或等初始化项,而成员中的构造函数将占上风。因此,对于省略了大小的数组成员,表达式就会出现格式错误.§12.6.2第9项更明确地说明,如果构造函数执行mem-初始化,r值初始化器表达式将被省略。

此外,谷歌集团的讨论C++中另一个不协调的行为,进一步阐述和使它更加清晰。它扩展了解释大括号或相等初始化器是在成员的内部初始化不存在的情况下的成员内部初始化的一种光荣方式的概念。作为一个例子

代码语言:javascript
运行
复制
struct Foo {
    int i[5] ={1,2,3,4,5};
    int j;
    Foo(): j(0) {};
}

等于

代码语言:javascript
运行
复制
struct Foo {
    int i[5];
    int j;
    Foo(): j(0), i{1,2,3,4,5} {};
}

但现在我们看到,如果省略数组大小,则表达式的格式将不正确。

但是,如果成员不是由成员内构造函数初始化初始化的,但是为了统一起见,编译器本来可以支持这个特性,但是与其他许多事情一样,标准也不支持这个特性。

票数 5
EN

Stack Overflow用户

发布于 2015-04-12 18:56:44

如果允许编译器支持您所描述的内容,并且将str的大小推断为5

代码语言:javascript
运行
复制
Foo foo = {{"This is not a test"}};

会导致未定义的行为。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29593207

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档