Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implicitly calling copy constructor

Tags:

c++

Consider:

struct Foo
{
    Foo(std::string str) {}
};

struct Bar
{
    Bar(Foo f) {}
};

int main(int argc, char* argv[])
{
    Foo f("test");

    Bar b1(f);
    Bar b2(std::string("test"));
    Bar b3("test");

    return 0;
}

This fails to compile on the declaration of b3 ('cannot convert argument 1 from 'const char [5]' to 'Foo''). Which makes sense, because there is no direct way to convert the const char to a Foo. However, there is a way to convert the const char to a std::string, and then use that to construct a Foo (which is what is happening in b1 and b2), and that is what I want because it makes the API nicer to use (not having to instantiate a Foo or an std::string explicitly every time).

So my question is: is there a way to let the compiler implicitly call the Foo(std::string) copy constructor? In other words, is there a way to make a declaration like that of b3 work, let it be the same as b2, and without declaring a const char* copy constructor for Foo? (that last thing is the obvious way but my real code is of course not as simple as this, and I'd prefer not having to add const char* copy constructors and handling all of the other initialisation in the constructors correctly and keeping that in sync with the std::string copy constructor).

like image 670
Roel Avatar asked Jan 29 '15 14:01

Roel


People also ask

When copy constructor is implicitly called?

In C++, a Copy Constructor may be called for the following cases: 1) When an object of the class is returned by value. 2) When an object of the class is passed (to a function) by value as an argument. 3) When an object is constructed based on another object of the same class.

When copy constructor is used implicitly for what purpose?

The copy constructor is used only for initializations, and does not apply to assignments where the assignment operator is used instead. The implicit copy constructor of a class calls base copy constructors and copies its members by means appropriate to their type. If it is a class type, the copy constructor is called.

Does copy constructor call default constructor?

The answer is No. The creation of the object memory is done via the new instruction. Copy constructor is then in charge of the actual copying (relevant only when it's not a shallow copy, obviously). You can, if you want, explicitly call a different constructor prior to the copy constructor execution.

Can a copy constructor be made private?

Can a copy constructor be made private? Explanation: The copy constructor can be defined as private. If we make it private then the objects of the class can't be copied. It can be used when a class used dynamic memory allocation.


1 Answers

If c++11 is acceptable, you could add a delegating constructor to Foo which takes a const char* and just calls the other constructor:

struct Foo
{
    Foo(std::string str) {}
    Foo(const char* str) : Foo(std::string(str)) {}
};

Alternatively, you could use c++14's std::string literal:

using namespace::std::string_literals;
Bar b3("test"s);

You could also emulate a delegating constructor by having both constructors call a separate function:

struct Foo
{
    Foo(std::string str) { init(str); }
    Foo(const char* str) { init(str); }
    void init(std::string str) {}
};

The downside of the above is that you'll need to think carefully about anything you were doing in initialization lists that you now need to do in the body of init.

like image 51
TartanLlama Avatar answered Nov 15 '22 12:11

TartanLlama