如果在一行中声明了两个对象,它们的构造顺序是啥?

Posted

技术标签:

【中文标题】如果在一行中声明了两个对象,它们的构造顺序是啥?【英文标题】:If two objects are declared in a single line, in which order are they constructed?如果在一行中声明了两个对象,它们的构造顺序是什么? 【发布时间】:2016-06-04 07:38:10 【问题描述】:

假设一个类被定义为

class A 
//.....
;

现在我正在创建两个对象

A a,b;

ab 的创建顺序是什么?是标准定义的吗?

【问题讨论】:

声明中的逗号不是逗号操作符,它只是一个分隔符。 在这种情况下它不是逗号运算符。 @Zakkery 但它没有回答初始化对象的顺序。 @donjuedo ..我可以测试它,但我不知道结果是否依赖于实现 @donjuedo 如果答案引用了标准,则不会。 ;) 【参考方案1】:

来自 8 个声明符 [dcl.decl] 3:

声明中的每个 init-declarator 都被单独分析,就好像它本身在声明中一样。

继续说

一个包含多个声明符的声明通常等价于相应的声明序列,每个声明只有一个 声明者。那是 T D1, D2, ... Dn; 通常相当于 T D1; T D2; ... T Dn; 其中T 是一个声明说明符序列,每个Di 是一个初始化声明符。当其中一个引入的名称时发生异常 声明符隐藏了由 decl-specifiers 使用的类型名称,因此当在后续的 decl-specifiers 中使用相同的 decl-specifiers 时 声明,它们的含义不同。

你可以说它们是从左到右构造的。

【讨论】:

比我快 45 秒 :-) @pasha T D1,D2=D1; 按照规则变成T D1; T D2=D1; 所以是的。 嗯,它说'通常'。 @erip 它将调用D2 的副本构造函数。不是复制赋值运算符。 @HagenvonEitzen:主要示例是变量与类型同名时。 S S,T; 工作; S S; S T; 是一个错误。较新的例子是auto x=1; auto y=2.0; 工作; auto x=1,y=2.0; 是一个错误。这些是脚注提供的唯一例子。所以“通常”是,如果有的话,有点轻描淡写。【参考方案2】:

C++ 规范第 8 章 [dcl.decl],说:

声明中的每个 init-declarator 都被单独分析,就好像它 本身就在声明中。 (100)

脚注(100)接着说:

(100) 具有多个声明符的声明通常等价于 相应的声明序列,每个声明都带有一个声明符。 那是

T D1, D2, ... Dn;

通常等价于

 T D1; T D2; ... T Dn;

...然后列出一些例外情况,这些例外情况都不适用于这种简单的情况。

因此,您的问题的答案是对象是按照您列出它们的顺序构造的。不,它不是逗号运算符。

【讨论】:

在这种情况下,您如何理解“通常”? @SergeyA 通过阅读例外情况,在这种情况下“通常”变为“否”,然后将补语作为肯定的。 :) @erip,相当一个过程:) @SergeyA 我相信你知道,这是编写 C++ 时的游戏名称。 ;D【参考方案3】:

顺序是书面顺序,从左到右。此外,它不是逗号运算符,而只是声明符列表。当使用用户定义的逗号操作符时,顺序实际上是未指定的。

请参阅 comma operator 和 declarators。

【讨论】:

【参考方案4】:

a 将首先创建,然后是 b

在这种情况下,逗号将用作分隔符而不是运算符。

例如来自***:

    /**
      *  Commas act as separators in this line, not as an operator.
      *  Results: a=1, b=2, c=3, i=0
      */
     int a=1, b=2, c=3, i=0;

【讨论】:

【参考方案5】:

标准:

声明符 [dcl.decl]: 声明中的每个 init-declarator 都被单独分析,就好像它本身在声明中一样。

例子:

class A 
public:
    A(std::string const &s): name(s) 
     
        std::cout << "I am " << name << '\n'; 
    
    std::string name;
;

auto main() -> int

    A a("a"), b("b");

输出:

I am a
I am b

【讨论】:

这段代码并不能证明这是真的。标准报价是。

以上是关于如果在一行中声明了两个对象,它们的构造顺序是啥?的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中声明实例变量而不构造它们的好方法是啥? [关闭]

静态对象和全局对象的销毁顺序是啥?

在共享库中全局声明的非 POD 对象的语义是啥?

java中静态方法,静态变量,静态初始化器,构造函数,属性初始化都是啥时候调用的? 它们的先后顺序。

条款04:确定对象使用前已被初始化

控制静态对象构造函数的顺序