Search code examples
c++visual-c++-2010

Copy constructor is not called for copy-initialization or optimized?


If copy constructor is made private then in

Case 1: No error, the compiler doesn't care if the copy constructor was defined in class.

Case 2: Error, copy constructor is private and when it is made public, it is elided.

Does it directly optimizes the copy without being noticing that if the constructor was made private?

#include <string>
using std::string;

class T
{
    string s;
    T(const T &obj):s(obj.s){}
public:
    T(const string &str):s(str){}
};

int main()
{
    T a = ("Copy Initialization");     //Case: 1

    T b = T("Copy Initialization");    //Case: 2
}

Solution

  • Case 2 comes under 12.8/31 in N3225:

    A program is ill-formed if the copy/move constructor or the copy/move assignment operator for an object is implicitly odr-used and the special member function is not accessible.

    Just because the copy ctor is elided doesn't mean it isn't odr-used. 3.2/2:

    A member of a set of candidate functions is odr-used if it is selected by overload resolution when referred to from a potentially-evaluated expression. [Note: this covers calls to named functions (5.2.2), oper- ator overloading (Clause 13), user-defined conversions (12.3.2), allocation function for placement new (5.3.4), as well as non-default initialization (8.5). A copy constructor or move constructor is odr-used even if the call is actually elided by the implementation. —end note ]

    Beware of course that MSVC is not fully C++0x-compliant, because (a) C++0x isn't a standard yet, and isn't finalized; and (b) MSVC hasn't implemented everything up to date anyway. But this stuff isn't substantially changed from C++03, so I'm fairly confident the explanation still holds.

    Case 1 would come under this too, except that on the two C++03 compilers I've checked it doesn't get that far because there's no possible conversion from a string literal to T. I can't be bothered to check whether there are any additional conversion sequences allowed in C++0x, there could be a new clause anywhere :-)

    It's still a mystery to me why MSVC allows case 1 ever, even with a public copy ctor. Does it allow it in strict C++03 mode?