Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ - Direct and Copy Constructors

class UnusualClass
{
    int a;
    public:
        UnusualClass(int a){std::cout<<"Direct initialization"<<std::endl;}
        UnusualClass(const UnusualClass &n){std::cout<<"Copy initialization"; }
};


int main ()
{
    UnusualClass k1(5);    //Direct initialization
    UnusualClass k2=56;   //Copy initialization
    return 0;
}

Why does the compiler print out "Direct initialization" twice? I've done some research and found out that I might be getting copy constructor elision. Is it possible to get two different outcomes in these two cases? Also, when I use UnusualClass(const UnusualClass &n)=delete I get an error saying use of deleted function 'UnusualClass::UnusualClass(const UnusualClass&). Why would I get this error if it skips this constructor anyways?

I know I can get two different outcomes by using two constructors UnusualClass(int a); and UnusualClass(double b); but this trick doesn't seem quite right.

like image 738
Glavatar Avatar asked May 20 '18 10:05

Glavatar


1 Answers

Copy initialization doesn't mean the copy constructor must be called.

If T is a class type, and the cv-unqualified version of the type of other is not T or derived from T, or if T is non-class type, but the type of other is a class type, user-defined conversion sequences that can convert from the type of other to T (or to a type derived from T if T is a class type and a conversion function is available) are examined and the best one is selected through overload resolution. The result of the conversion, which is a prvalue temporary (until C++17) prvalue expression (since C++17) if a converting constructor was used, is then used to direct-initialize the object. The last step is usually optimized out and the result of the conversion is constructed directly in the memory allocated for the target object, but the appropriate constructor (move or copy) is required to be accessible even though it's not used. (until C++17)

In the process of this copy initialization (i.e. UnusualClass k2=56;), UnusualClass::UnusualClass(int) will be selected for converting int to UnusualClass, so it's called at first. After that the converted UnusualClass is used to direct-initialize the object k2, so the copy constructor is required conceptually. Before C++17 even copy elision happens the copy constructor must be accessible, that's why when you make it delete you failed to compile. Since C++17 copy elision is guaranteed, and the copy constructor doesn't need to be accessible again.

like image 170
songyuanyao Avatar answered Sep 29 '22 06:09

songyuanyao