这个问题与下面转载的code snippet有关:
struct A {
A():b(0) { }
A(const A&, int b = 0):b(b) { }
int b;
};
int main() {
A a;
const A& a1 = { a };
const A& a2 = { a, 1 };
a.b = 2;
std::cout << a1.b << a2.b << std::endl;
}
a1赋值的右侧可以是构造中的单个值,也可以是构造的参数列表。标准中是否有任何指定哪种解释优先?对于a2,它是一个临时A的结构,如果我没有误解,它的地址被分配给a2。
BTW,在Coliru中用clang ++编译这段代码产生了输出21. gcc ++ - 4.8输出01.
答案 0 :(得分:5)
自由于缺陷报告发布C ++ 11标准以来,列表初始化的定义发生了很大变化。
来自草案n3485(标准版发布后,有一些更正但没有C ++ 1y功能)[dcl.init.list] / 3
类型
T
的对象或引用的列表初始化定义如下:
- 如果
T
是汇总[...]- 否则,如果初始化列表没有元素[...]
- 否则,如果
的特化T
是std::initializer_list<E>
[...]- 否则,如果
T
是班级类型[...]- 否则,如果初始化列表包含
E
类型的单个元素且T
不是引用类型或其引用类型与E
引用相关,则对象或引用从该元素初始化;如果将元素转换为T
需要缩小转换,则程序格式不正确。- 否则,如果
T
是引用类型,则T
引用的类型的prvalue临时值被列表初始化,并且引用绑定到该临时- [...]
在委员会的github回购(ce016c64dc)的最新草案中,这里只有一点点变化[dcl.init.list] / 3:
- 否则,如果
T
是引用类型,T
引用的类型的prvalue临时是copy-list-initialized或direct-list-initialized,具体取决于初始化的类型。引用,引用绑定到临时引用。
来自草案n3242(标准之前)[dcl.init.list] / 3:
类型
T
的对象或引用的列表初始化定义如下:
- 如果初始化列表没有元素[...]
- 否则,如果
T
是汇总[...]- 否则,如果
的特化T
是std::initializer_list<E>
[...]- 否则,如果
T
是班级类型[...]- 否则,如果
T
是对类类型的引用,或者T
是任何引用类型且初始化列表没有元素,则T
引用的类型的prvalue临时值为list-initialized,引用绑定到那个临时的。- [...]
(我现在没有标准本身的副本。)
假设您的编译器实现了对缺陷报告的建议解决方案。然后,第一个例子
const A& a1 = { a };
初始化为const A& a1 = a;
(无临时);和第二个例子
const A& a2 = { a, 1 };
初始化为const A& a2 = A(a,1);
。
答案 1 :(得分:1)
8.5.4 / 3 对象或类型T的引用的列表初始化定义如下:
...
- 否则,如果T是引用类型,则由T引用的类型的prvalue临时列表进行列表初始化,并且引用绑定到 那是暂时的。
在您的示例中,a1
不直接绑定到a
,而是绑定到a
构建的临时副本。