简体   繁体   中英

Private copy constructor and constructor with one argument

Why this code can't compile? If i'll change copy constructor access level to public, it'll be ok and print "Foo::Foo(int)". If i'll write "Foo instance(0);" instead of "Foo instance = 0;" it'll also ok. Why? And what's the point of this behavior?

#include <iostream>

struct Foo
{
public:
   int i;
   Foo(int i) : i(i) { std::cout << "Foo::Foo(int) \n"; }

private:
   Foo(const Foo&) { std::cout << "Foo::Foo(const Foo&) \n"; }
};

int main()
{
   Foo instance = 0;
}

Foo instance = 0; uses copy initialization. The 0 is converted to a Foo object using the non-explicit constructor Foo(int i) which is then copied to make instance . It is equivalent to:

Foo instance = Foo(0);

This requires the copy constructor which you have made private.

When you make it public, the reason the conversion constructor prints but the copy constructor does not is because the copy can be elided by the compiler for optimization. It's the one form of optimization that may change the execution of your code. The copy constructor still needs to be public, however, regardless of whether it is elided or not. In other words, the copy needs to be possible before it can be elided.

If you make the conversion constructor explicit , it won't compile:

explicit Foo(int i) : i(i) { std::cout << "Foo::Foo(int) \n"; }

Because

Foo instance = 0;

is copy initialization and requires an accessible copy constructor. It attempts to create a temporary Foo from 0 , using the conversion constructor, and then create instance from the temporary Foo using the copy constructor.

By contrast,

Foo instance(0);

is direct initialization and only requires the conversion constructor.

Related: What's the motivation behind having copy and direct initialization behave differently?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM