When is the compiler allowed to optimize the initialization of the auto + parenthesis style?

Suppose you have a class called Product, defined as follows:

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

and you initialize the variable as follows:

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

I thought the standard dictates that the compiler should logically do the following:

  • create a temporary product
  • move-construct p (using a temporary product)

But the compiler was allowed to optimize it so that p was built directly.

I checked this (Visual Studio 2013), and indeed, the compiler optimizes this, even if we have our own custom (non-standard) move-constructor. This is normal.

However, if I explicitly remove the copy and move constructor, for example:

 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 + brace initialization is still compiling. I, although the compiler should have prevented this, because copying or moving is not allowed.

It is strange if I make a private instance of private-copy-move-move, like this:

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

Then auto + brace initialization is no longer a compiler.

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

Is this the expected behavior? Is this a bug in Visual Studio 2013 (Update 3)?

Note: I tried to compile this on ideone , and there it really refuses to compile initialization when copies and move-constructors are deleted (and publicly accessible), so I think this is a Visual Studio error.

+6
source share
2 answers

the standard is very clear, as you mentioned earlier, indicating that this is a bug in the cl compiler. You can never be sure, although if one compiler says something and everyone else disagrees, I expect this to be one of many non-standard implementations of the MSVC compiler.

Interpretation of clang version 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: *** [to] Error 1 

Interpretation of 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/to] Error 1 

Keep in mind that Explicitly deactivated and removed features are new because MSVC 2013 and its implementation are not yet complete. For example, he has not yet understood = default for move constructors.

I assume that MSVC 2013 does not validate the move constructor, or simply returns to the copy constructor.

It might be interesting to check out MSVC 2015, as it seems to have (more) full implementation of these constructs.

Jvapen

+1
source

In your line

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

the equal sign does not denote the assignment operator, but is only the syntax for the initializer. Therefore, the compiler does not optimize anything, but simply performs initialization.

0
source

Source: https://habr.com/ru/post/989824/


All Articles