3

From what I learned, I thought Foo a = 1 is equivalent to Foo a = (Foo)1.

With copy constructor declared, yes, they both result in calling Converting constructor.

class Foo
{
public:
    // Converting constructor
    Foo(int n) : value_(n) { std::cout << "Converting constructor." << std::endl; }

    // Copy constructor
    Foo(const Foo&) { std::couut << "Copy constructor." << std::endl; }

private:
    int value_;
};

int main()
{
    Foo a = 1;         // OK - prints only "Converting constructor."
    Foo b = (Foo)1;    // OK - prints only "Converting constructor."
}

In contrast, without copy constructor, it doesn't compile even though it doesn't ever call copy constructor.

class Foo
{
public:
    // Converting constructor
    Foo(int n) : value_(n) { std::cout << "Converting constructor." << std::endl; }
    
    // Copy constructor deleted
    Foo(const Foo&) = delete;

private:
    int value_;
};

int main()
{
    Foo a = 1;         // OK - prints only "Converting constructor."
    Foo b = (Foo)1;    // Error C2280: 'Foo::Foo(const Foo &)': attempting to reference a deleted function
}

What makes difference? Thank you.

Jeongmin Heo
  • 61
  • 1
  • 7

1 Answers1

4

Foo a = 1; calls Foo(int n). (Foo)1 also calls Foo(int n). Foo b = (Foo)1; calls copy constructor Foo(const Foo&). Until C++17 the last call can be elided but the copy constructor must be available. Since C++17 copy elision is mandatory and the copy constructor isn't necessary: https://en.cppreference.com/w/cpp/language/copy_elision

Probably you're using a C++ standard before C++17 and the copy constructor is required but not called.

"From what I learned, I thought Foo a = 1 is equivalent to Foo a = (Foo)1." That's not equivalent. The first is one constructor call and the second is two constructor calls but one call can/must be elided.

Thomas Sablik
  • 16,127
  • 7
  • 34
  • 62