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

时间:2015-06-26 16:13:37

标签: c++ visual-studio-2013 auto list-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};

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

  • 构建临时产品
  • 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;
   };

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

奇怪的是,如果我将删除的copy-and 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;
   };

然后auto + brace初始化不再编译。

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

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

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

2 个答案:

答案 0 :(得分:1)

如前所述,标准非常清晰,表明这是cl-compiler中的一个错误。你永远无法确定,虽然如果一个编译器说了些什么而其他所有人都不同意,我希望这将是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

请记住Explicitly Defaulted and Deleted Functions自MSVC 2013以来是新的,并且其实施尚未完成。就像它还没有理解=移动构造函数的默认值。

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

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

JVApen

答案 1 :(得分:0)

在你的行

auto p = Product{"abc",123};

等号不是表示赋值运算符,而只是初始值设定项的语法。因此,编译器没有优化任何东西,只是进行初始化。