什么时候编译器允许优化自动+大括号样式初始化?

Pat*_*ick 6 c++ auto list-initialization visual-studio-2013

假设您有一个名为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;
   };
Run Code Online (Sandbox Code Playgroud)

并初始化一个这样的变量:

auto p = Product{"abc",123};
Run Code Online (Sandbox Code Playgroud)

我认为标准规定编译器必须在逻辑上执行以下操作:

  • 构建临时产品
  • move-construct p(使用临时产品)

但是允许编译器优化它以便直接构造p.

我验证了这一点(Visual Studio 2013),实际上,即使我们有自己的自定义(非默认)移动构造函数,编译器也会优化它.这可以.

但是,如果我明确删除了copy-和move-构造函数,如下所示:

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;
   };
Run Code Online (Sandbox Code Playgroud)

auto +大括号初始化仍然编译.我虽然编译器必须防止这种情况,因为没有复制或移动允许.

奇怪的是,如果我将删除的copy-和move-构造函数设为私有,如下所示:

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;
   };
Run Code Online (Sandbox Code Playgroud)

然后auto +大括号初始化不再编译.

error C2248: 'Product::Product' : cannot access private member declared in class 'Product'
Run Code Online (Sandbox Code Playgroud)

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

注意:我尝试在ideone上编译它,并且当复制和移动构造函数被删除(和公共)时,它确实拒绝编译初始化.所以我认为这是一个Visual Studio错误.

JVA*_*pen 1

正如您之前提到的,标准非常明确,表明这是 cl 编译器中的错误。你永远无法确定,但如果一个编译器说了某件事而所有其他编译器不同意,我预计这将是 MSVC 编译器的众多不符合标准的实现之一。

\n\n

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

\n\n
t.cpp:19:7:{19:11-19:30}: error: call to deleted constructor of \'Product\'\n      [Semantic Issue]\n        auto p = Product{"abc", 123};\n              ^   ~~~~~~~~~~~~~~~~~~~\nt.cpp:8:2: note: \'Product\' has been explicitly marked deleted here\n      [Semantic Issue]\n        Product(Product &&rhs) = delete;\n         ^\n1 error generated.\nmake: *** [t.o] Error 1\n
Run Code Online (Sandbox Code Playgroud)\n\n

gcc 4.8的解释:

\n\n
t.cpp: In function \xe2\x80\x98int main()\xe2\x80\x99:\nt.cpp:19:29: error: use of deleted function \xe2\x80\x98Product::Product(Product&&)\xe2\x80\x99\n  auto p = Product{"abc", 123};\n                             ^\nt.cpp:8:2: error: declared here\n  Product(Product &&rhs) = delete;\n  ^\nmake: *** [build/gcc/t.o] Error 1\n
Run Code Online (Sandbox Code Playgroud)\n\n

另请记住,显式默认和删除的函数是自 MSVC 2013 以来的新函数,并且其实现尚未完成。就像它还不理解移动构造函数的 =default 一样。

\n\n

我的猜测是,MSVC 2013 不会检查移动构造函数,或者只是退回到复制构造函数。

\n\n

检查 MSVC 2015 可能会很有趣,因为它似乎对这些结构有(更)完整的实现。

\n\n

JVA笔

\n