何时允许编译器优化自动括号样式的初始化?

帕特里克

假设您有一个名为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),实际上,即使我们有自己的自定义(非默认)移动构造函数,编译器也会对此进行优化。这可以。

但是,如果我明确删除了copy-和move-constructor,如下所示:

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;
   };

自动括号初始化仍然可以编译。尽管编译器必须防止这种情况,因为不允许复制或移动。

奇怪的是,如果我将删除的copy-和move-constructor设为私有,则如下所示:

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;
   };

然后,自动括号初始化不再编译。

error C2248: 'Product::Product' : cannot access private member declared in class 'Product'

这是预期的行为吗?这是Visual Studio 2013(更新3)中的错误吗?

注意:我尝试在ideone上进行编译,并且在复制和移动构造函数被删除(并公开)后,它确实拒绝编译初始化。所以我认为这是Visual Studio的错误。

JVApen

正如您前面提到的,该标准非常明确,表明这是cl编译器中的错误。您永远无法确定,尽管如果一个编译器在说些什么而其他所有人都不同意,我希望这将是MSVC编译器的许多不符合标准的实现之一。

clang版本3.7(svn-build)的解释:

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以来,“显式默认和删除的功能”是新功能,其实现尚未完成。好像还不了解move构造函数的= default。

我的猜测是,MSVC 2013不会检查move构造函数,或者只是回退到copy构造函数。

检查MSVC 2015可能会很有趣,因为它似乎已经(完全)实现了这些构造。

JVApen

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

编译器会优化集合初始化吗?

为什么编译器不优化此初始化?

为什么在某些优化级别上,编译器会警告未初始化的边缘迭代器?

为什么编译器将带有方括号()的数组初始化标记为错误?

编译器说变量尚未初始化

为什么编译器禁止初始化数组?

多变量初始化编译器支持

(C ++)使用花括号和右值初始化时发生内部编译器错误

使用列表初始化时,C ++语言是否会强制执行编译器优化?

自动属性何时初始化?

当括号括起来的列表中的初始化程序少于集合中的元素或成员时,C编译器如何声明数组?

如何避免使用大向量初始化的“编译器限制:编译器堆栈溢出”?

无法初始化编译器:在编译器镜像中找不到对象java.lang.Object

现代C ++编译器会自动将局部变量初始化为0吗?

何时允许编译器优化 C++ 中枚举或枚举类类型值的有效性检查?

初始化多维数组时,编译器如何解释不完整的初始化列表?

为什么在尝试使用C ++ 11样式初始化对象数组时编译器隐式删除构造函数

编译器无法识别std :: vector的成员初始化器

对TypeScript使用@Prop装饰器-编译器出现错误要求初始化prop

GLSL编译器会删除不必要的变量初始化吗?

Kotlin:“同步”使编译器不确定变量的初始化

编译器未检测到明显未初始化的变量

catch块中的throw语句如何防止未初始化变量的编译器错误?

未初始化变量的错误编译器错误用法

为什么Kotlin编译器需要var属性的显式初始化程序?

如何在不得到编译器警告的情况下初始化char * args []

Mac上的Spark Shell“无法初始化编译器”错误

gcc编译器将忽略未初始化的变量警告以进行调试

如何强制编译器为未初始化的变量设置非零值?