请问 为什么C+11类初始化器不能使用括号?

为什么C+11类初始化器不能使用括号?

例如,我不能这样写:

class A{
    vector<int> v(12, 1);};

我只能这样写:

class A{
    vector<int> v1{ 12, 1 };
    vector<int> v2 = vector<int>(12, 1);};

C+11语言设计的不同之处在于什么?


繁星coding
浏览 334回答 2
2回答

鸿蒙传说

这一选择背后的理由在相关的提案为非静态数据成员初始化器&nbsp;:在科纳提出的关于识别资料范围的问题:在2007年9月在科纳举行的核心工作组讨论期间,出现了一个关于初始化程序中标识符的范围的问题。我们想要允许类作用域与前向查找的可能性;还是我们想要求初始化程序在解析后被很好地定义?想要什么:类范围查找的动机是,我们希望能够将任何内容放入非静态数据成员的初始化器中,这样就可以在不显着改变语义的情况下将其放入mem初始化程序中(模块直接初始化与复制初始化):int&nbsp;x();struct&nbsp;S&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;i; &nbsp;&nbsp;&nbsp;&nbsp;S()&nbsp;:&nbsp;i(x())&nbsp;{}&nbsp;//&nbsp;currently&nbsp;well-formed,&nbsp;uses&nbsp;S::x() &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;... &nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;int&nbsp;x();};struct&nbsp;T&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;i&nbsp;=&nbsp;x();&nbsp;//&nbsp;should&nbsp;use&nbsp;T::x(),&nbsp;::x()&nbsp;would&nbsp;be&nbsp;a&nbsp;surprise &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;... &nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;int&nbsp;x();};问题1:不幸的是,在解析声明时,这使得“(表达式-列表)”形式的初始化器变得模糊不清:&nbsp;&nbsp;&nbsp;struct&nbsp;S&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;i(x);&nbsp;//&nbsp;data&nbsp;member&nbsp;with&nbsp;initializer &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;... &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;int&nbsp;x; &nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;T&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;i(x);&nbsp;//&nbsp;member&nbsp;function&nbsp;declaration &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;... &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typedef&nbsp;int&nbsp;x; &nbsp;&nbsp;&nbsp;&nbsp;};一个可能的解决方案是依赖现有的规则,如果声明可以是对象或函数,那么它就是一个函数:&nbsp;struct&nbsp;S&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;i(j);&nbsp;//&nbsp;ill-formed...parsed&nbsp;as&nbsp;a&nbsp;member&nbsp;function, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;type&nbsp;j&nbsp;looked&nbsp;up&nbsp;but&nbsp;not&nbsp;found &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;... &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;int&nbsp;j; &nbsp;&nbsp;&nbsp;&nbsp;};类似的解决方案是应用另一条现有规则,目前仅在模板中使用,即如果T可以是类型或其他类型,那么它就是另一种类型;如果我们真正指的是类型,则可以使用“type Name”:struct&nbsp;S&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;i(x);&nbsp;//&nbsp;unabmiguously&nbsp;a&nbsp;data&nbsp;member &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;j(typename&nbsp;y);&nbsp;//&nbsp;unabmiguously&nbsp;a&nbsp;member&nbsp;function &nbsp;&nbsp;&nbsp;&nbsp;};这两种解决方案都引入了许多可能被许多用户误解的微妙之处(如comp.lang.c+中关于为什么“intI();”at块作用域不声明默认初始化的int)的许多问题所证明的那样。本文提出的解决方案是只允许“=初始化-子句”和“{初始化-列表}”形式的初始化程序。..,这解决了最例如:HashingFunction&nbsp;hash_algorithm{"MD5"};在这里,我们不能使用=表单,因为HasningFunction的构造函数是显式的。在特别棘手的情况下,可能需要两次提到一个类型。考虑:&nbsp;&nbsp;&nbsp;vector<int>&nbsp;x&nbsp;=&nbsp;3;&nbsp;//&nbsp;error:&nbsp;&nbsp;the&nbsp;constructor&nbsp;taking&nbsp;an&nbsp;int&nbsp;is&nbsp;explicit &nbsp;&nbsp;&nbsp;vector<int>&nbsp;x(3);&nbsp;&nbsp;//&nbsp;three&nbsp;elements&nbsp;default-initialized &nbsp;&nbsp;&nbsp;vector<int>&nbsp;x{3};&nbsp;&nbsp;//&nbsp;one&nbsp;element&nbsp;with&nbsp;the&nbsp;value&nbsp;3在这种情况下,我们必须使用适当的表示法在这两种选择之间进行选择:vector<int>&nbsp;x&nbsp;=&nbsp;vector<int>(3);&nbsp;//&nbsp;rather&nbsp;than&nbsp;vector<int>&nbsp;x(3);vector<int>&nbsp;x{3};&nbsp;//&nbsp;one&nbsp;element&nbsp;with&nbsp;the&nbsp;value&nbsp;3问题2:另一个问题是,由于我们不建议修改初始化静态数据成员的规则,添加静态关键字可能会使格式良好的初始化器不正确:&nbsp;&nbsp;&nbsp;struct&nbsp;S&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;int&nbsp;i&nbsp;=&nbsp;f();&nbsp;//&nbsp;well-formed&nbsp;with&nbsp;forward&nbsp;lookup &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;const&nbsp;int&nbsp;j&nbsp;=&nbsp;f();&nbsp;//&nbsp;always&nbsp;ill-formed&nbsp;for&nbsp;statics &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;... &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;constexpr&nbsp;static&nbsp;int&nbsp;f()&nbsp;{&nbsp;return&nbsp;0;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;};问题3:第三个问题是类范围查找可能将编译时错误转换为运行时错误:struct&nbsp;S&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;i&nbsp;=&nbsp;j;&nbsp;//&nbsp;ill-formed&nbsp;without&nbsp;forward&nbsp;lookup,&nbsp;undefined&nbsp;behavior&nbsp;with &nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;j&nbsp;=&nbsp;3;};(除非被编译器捕获,否则我可能会使用未定义的值j)。建议:CWG在科纳进行了6比3的民意调查,支持类范围查找;这也是本文所建议的,非静态数据成员的初始化器仅限于“=initiators-子句”和“{initiator-list}”表单。我们认为:问题1:这个问题不会发生,因为我们没有提出()表示法。=和{}初始化符号不受此问题的影响。问题2:添加静态关键字会产生许多差异,这是其中最小的差异。问题3:这不是一个新问题,而是与构造函数初始化器已经存在的初始化顺序相同的问题。
打开App,查看更多内容
随时随地看视频慕课网APP