对象创建订单在支撑初始化列表中
Object creation order in braced init list
#include <iostream>
struct A
{
A() { std::cout << "(A::A)"; }
};
struct B
{
B() { std::cout << "(B::B)"; }
};
struct C
{
template<typename ...Args>
C(Args && ...) {}
};
int main(int agrc, char *argv[])
{
C {A(), B()}; // <-- prints (B::B)(A::A)
std::cout << std::endl;
C {(A(), B())}; // <-- prints (A::A)(B::B)
std::cout << std::endl;
return 0;
}
我有2个问题:
- 为什么在第一个支撑启动列表中以左顺序创建对象?
- 为什么在第二种情况下括号还原?
编辑:我已将其编译为MSVS 2013
在第二个实例中,实际上您仅使用B()
初始化;通过使用逗号操作员,A()
首先构造并扔掉。
C {(A(), B())};
//|^^^^^^^^^^|
// --------> (A(), B())
// ^^^ ^^^
// | |
// /
// evaluated, THEN evaluated,
// discarded used
另一方面,首先,您是通过 emarties einitializer列表来初始化的 C
,当时还应将其元素从左到右进行评估,但是您的编译器在这方面是越来越大的:
[C++11: 8.5.4/4]:
braced-init-list , initializer-clauses 的 initializer-list ,包括包装扩展产生的任何结果(14.5.3),以它们出现的顺序进行评估。也就与任何 initializer-clause 相关的值计算和副作用,这些在 initizer-initiber-list-list-list 的逗号分隔列表中。 [注意:此评估顺序不管初始化的语义如何;例如,当 initiber-list 的元素被解释为构造函数调用的参数时,它也适用,尽管通常对调用的参数没有测序约束。 - end Note]
我可以用GCC 4.8 *重现问题,但是Clang 3.5行为正确&Dagger; 。该错误已在&ddagger; 之前的 std-discussion 列表上进行了讨论,但是我还没有找到GCC Bugzilla ID &sect>&sect; 。
C {A(), B()};
// ^^^ ^^^
// |
// eval- THEN
// uated evaluated
// /
// /
// both used
* http://coliru.stacked-crooked.com/a/a/1f18e0d1f8973f3f3c
&Dagger; http://coliru.stacked-crooked.com/a/a/5a6e7506e9be97c3
&Ddagger; https://groups.google.com/a/isocpp.org/forum/# !! Topic/std-discussion/tqunbfkubdg
&sect; #51253可能是相关的。
为什么在第一个支撑启动列表中以左顺序创建对象?
否。它是从左到右的。您的编译器有错误,这就是为什么它正在评估左右的原因。已知 GCC(4.8)具有此错误。您是否使用GCC?
为什么在第二种情况下括号还原?
相同。左到右。在这种情况下,逗号操作员会出现图片,该操作数从左到右评估。
它是GCC 4.8.1(我想您使用GCC)或其他编译器的旧错误。我几个月前写了这个错误初始化列表:GCC 4.8.1
的错误尽管它是用俄语编写的,但您可以使用例如Google服务翻译将其翻译成英文。
由初始化列表的其他元素从左到右评估,并在评估下一个元素之前应用所有副作用。
在第二个代码示例中,您实际上将构造函数称为conma运算符的表达式。逗号运算符的行为与初始器列表相同的方式是它从左到右评估其操作数,并在评估下一个操作数之前应用副作用。
- C++类 - 初始化列表 - 递归 - 按值传递
- 在初始化列表之外手动调用基类的构造函数
- C++:带有大括号初始化列表的函数调用表达式 - 标准是否规定在单个元素列表的微不足道的情况下忽略大括号?
- std::map与谓词与初始化列表
- 类内初始化与构造函数初始化列表的顺序
- 当返回语句时,逗号运算符、大括号初始化列表和 std::unique_ptr 组合在一起
- 使用初始化列表填充C++中的多维结构数组时出现问题
- 如何在初始化列表中的构造函数之后初始化变量/对象?
- C++初始化列表与分配值
- C++初始化列表中的向量集大小或调整大小
- 在构造函数初始化列表中使用 std::variant
- emplace_back初始化列表错误,当初始化列表在独立变量上工作时
- 解释了构造函数成员初始化列表
- 使用初始化列表时如何获取私有数据?
- 用初始化列表和超类构造函数声明子类构造函数的正确方式
- 如何在成员初始化列表中声明共享指针
- 庞大的初始化列表,如何修复"fatal error C1060: compiler is out of heap space"
- 我可以检查初始化列表中设置的构造函数主体中的变量吗
- 使用整数初始化列表初始化长双精度的向量
- 是否可以在C++中使用初始化列表设置数组的特定成员?