何时允许编译器优化auto+大括号样式的初始化
When is the compiler allowed to optimize auto+brace style initialization?
假设您有一个名为Product的类,定义如下:
class Product
{
public:
Product(const char *name, int i);
Product(Product &&rhs);
Product(const Product &rhs);
~Product();
private:
const char *m_name;
int m_i;
};
然后初始化一个类似这样的变量:
auto p = Product{"abc",123};
我认为标准规定编译器必须在逻辑上执行以下操作:
- 构造临时产品
- 移动构造p(使用临时产品)
但编译器被允许对此进行优化,以便直接构造p。
我验证了这一点(Visual Studio 2013),事实上,编译器对此进行了优化,即使我们有自己的自定义(非默认)移动构造函数。这很好。
但是,如果我显式地删除复制和移动构造函数,如下图所示:
class Product
{
public:
Product(const char *name, int i);
Product(Product &&rhs) = delete;
Product(const Product &rhs) = delete;
~Product();
private:
const char *m_name;
int m_i;
};
auto+大括号初始化仍在编译。我认为编译器必须阻止这种情况,因为不允许复制或移动。
奇怪的是,如果我将已删除的复制和移动构造函数设为私有,就像这样:
class Product
{
public:
Product(const char *name, int i);
~Product();
private:
Product(Product &&rhs) = delete;
Product(const Product &rhs) = delete;
const char *m_name;
int m_i;
};
那么auto+大括号初始化就不再编译了。
error C2248: 'Product::Product' : cannot access private member declared in class 'Product'
这是预期的行为吗?这是Visual Studio 2013(更新3)中的错误吗?
注:我试着在ideone上编译它,当复制和移动构造函数被删除(并且是公共的)时,它确实拒绝编译初始化。所以我认为这是一个VisualStudio错误。
正如您之前提到的,标准非常清晰,表明这是cl编译器中的一个错误。你永远无法确定,尽管如果一个编译器在说什么,而所有其他编译器都不同意,我预计这将是MSVC编译器的许多不符合标准的实现之一。
clang版本3.7的解释(svn构建):
t.cpp:19:7:{19:11-19:30}: error: call to deleted constructor of 'Product'
[Semantic Issue]
auto p = Product{"abc", 123};
^ ~~~~~~~~~~~~~~~~~~~
t.cpp:8:2: note: 'Product' has been explicitly marked deleted here
[Semantic Issue]
Product(Product &&rhs) = delete;
^
1 error generated.
make: *** [t.o] Error 1
解释gcc 4.8:
t.cpp: In function ‘int main()’:
t.cpp:19:29: error: use of deleted function ‘Product::Product(Product&&)’
auto p = Product{"abc", 123};
^
t.cpp:8:2: error: declared here
Product(Product &&rhs) = delete;
^
make: *** [build/gcc/t.o] Error 1
还要记住,自MSVC 2013以来,显式默认和删除函数是新的,其实现尚未完成。就像它还不理解=默认移动构造函数一样。
我的猜测是MSVC 2013不检查移动构造函数,或者只是返回到复制构造函数。
查看MSVC 2015可能会很有趣,因为它似乎已经(更)完整地实现了这些构造。
JVApen
在您的行中
auto p = Product{"abc",123};
等号不是表示赋值运算符的符号,而只是初始化器的语法。因此,编译器不是在优化任何东西,而是在进行初始化。
- C++ C 样式零初始化 { 0 }.
- 是否可以在编译时初始化对象的 C 样式函数指针,以便它调用对象的成员函数?
- 可视C++初始化样式
- 如何从嵌套的 std::initializer_list 初始化 2D C 样式数组?
- 此代码中的数组初始化样式是什么?这是标准的吗?
- 初始化有关Google C 样式指南的静态字符串(C-Type或STD :: String)
- 为什么编译器在试图初始化具有C 11样式的对象数组时隐含删除构造函数
- 用于 protobuf 转换的大括号初始化样式构造函数
- 如何在调用 DDX_Control 之前更改使用 DDX_Control 初始化的控件 (CListBox) 的样式
- 课堂初始化(分配样式)与构造函数性能
- 如何将初始值设定项与右值引用参数一起使用 // 为什么不能使用另一个 C 样式数组变量初始化 C 样式数组
- C++ 使用 C 样式数组聚合初始化
- 初始化不正确的价值不良样式后,正在抛出异常
- 如何在使用g++编译器时使用c样式初始化结构
- QObject 自定义属性何时从样式表中指定的值初始化
- 为什么在初始化项列表中初始化 POD 数据时必须使用 C 样式类型转换
- c++初始化动态内存中c样式字符串的默认值
- 初始化c样式结构
- 可以用不同的大括号处理数组初始化的样式
- 何时允许编译器优化auto+大括号样式的初始化