Private constructor / copy operator and copy-initialization

This is a question of this question.

in the following code why compiling line 1 while lines 2 and 3 are not used (using Visual C ++ 2010)

class ABase { protected: ABase() {} ~ABase() {} private: ABase( const ABase& ); const ABase& operator=( const ABase& ); }; class A : ABase { }; class B { public: B() {} ~B() {} private: B( const B& ); const B& operator=( const B& ); }; int main( void ) { A a = A(); // line 1 A a2( a ); // line 2 B b = B(); // line 3 return 0; } 

(BA note is a copy of boost :: noncopyable)

edit My problem is not to know why lines 2 and 3 do not compile (I know that the copy constructor is private), but why line 1 does.

+8
c ++ boost
source share
6 answers

The compiler is mistaken in accepting the first use. Even if the copy is complete, the copy constructor must be available for the correct code.

In this particular case, there is an implicitly declared copy constructor in A :

Β§12.8 / 4 If the class definition does not explicitly declare the copy constructor, it is declared implicitly.

This is implicitly defined:

Β§12.8 / 7 An implicitly declared copy constructor is implicitly defined if it is used to initialize an object of its class type from a copy of an object of its class type or a class type obtained from its class type108). [Note: the copy constructor is implicitly defined, even if the implementation has accelerated its use (12.2). ] A program is poorly formed if the class for which the copy constructor is implicitly defined has:

- a non-static data member of the class type (or its array) with an inaccessible or ambiguous copy constructor, or

- base class with inaccessible or ambiguous copy constructor.

+5
source share

Indeed, line 1 should not be compiled.

Obviously, vC ++ 2010 has problems complying with the language rules in this case (maybe because they are associated with the base class, and not with the object itself).

Diagnostic message

g ++ about line 1 is very clear

 ncopy.cpp: In copy constructor 'A::A(const A&)': ncopy.cpp:7: error: 'ABase::ABase(const ABase&)' is private ncopy.cpp:12: error: within this context ncopy.cpp: In function 'int main()': ncopy.cpp:27: note: synthesized method 'A::A(const A&)' first required here 
+6
source share
 ABase( const ABase& ); 

The copy constructor becomes private, so a copy of the class object cannot be created using this private copy constructor, which leads to an error.

 A a = A(); // line 1 

Uses A::A(const A&) to create a new object A A obtained from ABase , and it calls ABase::ABase(const ABase&) in its constructor, which is private to it, will not compile either.

Below is the output on Ideone. It does not compile even on gcc.

Why does this work on Visual Studio?
The reason is a possible Optimization of the return value by the visual C ++ compiler, which returns the copy constructor.

According to the C ++ 12.8 standard, copying class class objects

When certain criteria are met, implementations are allowed to omit the copy construction of the class object, even if the copy constructor and / or destructor for the object have side effects. In such cases, the implementation considers the source and purpose of the omitted copy operation as just two different ways of accessing the same object, and the destruction of this object occurs at later times when two objects would be destroyed without optimization .111)

See my answer here , which refers to standard and sample code in this regard.

 A a2( a ); // line 2 

It does not compile for the same reason that ABase::ABase(const ABase&) is closed.

  B b = B(); // line 3 

It does not compile because B( const B& ); is closed.

+2
source share

Line 1 is the optimization of the return value (the compiler sees that there is no need to create a temporary variable for A() and use the copy / assign statement constructor to assign the variable a )). However, this does not compile on GCC (version 4.2.1) and should be avoided.

Line 2 does not compile, because in this case the compiler does not create an assignment operator for you. Line 3 does not compile as you expect.

Reagan Summary: Line 1 works because Microsoft, others behave as expected.

+1
source share

Why is line 1 compiling? Because your compiler is broken; it should not, in accordance with the standard. As long as your class A implicitly declared copy constructor, Β§12.8 / 7 of the standard states that An an implicitly declared copy constructor will be implicitly defined if it is used to initialize the object (as in A a = A(); ), and that the program (and, therefore, it requires diagnostics) if the constructor is implicitly defined, and the base class has an inaccessible or ambiguous copy of the constructor. There is even a note that this is so, even if the implementation excludes the copy constructor. You compiler is not far enough: it sees an implicitly declared public copy of the constructor, but it does not try to indirectly define it, although the standard clearly says that it should.

+1
source share

I believe this is because the constructor is protected, not private. The class A constructor provided by the compiler can invoke the ABase class protected constructor, so it works.

In addition, line 1 is not a copy constructor. An assignment declaration is a special case that translates to a constructor.

0
source share

All Articles