Consider the following class:
struct IntPointerWrapper
{
int* data_pointer;
IntPointerWrapper() : data_pointer(new int())
{
std::cout << "IntPointerWrapper()" << std::endl;
}
IntPointerWrapper(const IntPointerWrapper& other) : data_pointer(new int())
{
std::cout << "IntPointerWrapper(const IntPointerWrapper& other)" << std::endl;
*data_pointer = *other.data_pointer;
}
IntPointerWrapper& operator=(const IntPointerWrapper& other)
{
std::cout << "operator=(const IntPointerWrapper& other)" << std::endl;
*data_pointer = *other.data_pointer;
return *this;
}
~IntPointerWrapper()
{
std::cout << "~IntPointerWrapper() " << std::endl;
delete data_pointer;
}
};
And a simple factory method
IntPointerWrapper bar()
{
IntPointerWrapper q;
return q;
}
int main()
{
IntPointerWrapper m = bar();
}
I want to compile with disabled copy elision, to see how many times the copy constructor is called.
I get this output:
IntPointerWrapper()
IntPointerWrapper(const IntPointerWrapper& other)
~IntPointerWrapper()
IntPointerWrapper(const IntPointerWrapper& other)
~IntPointerWrapper()
~IntPointerWrapper()
So the copy constructor is called twice, but I'm not really getting why. Before running this experiment I would have bet that a single call were enough.
I'm wondering if there is any motivation behind these 2 copies instead of a single one, or it just something implementation specific.
I tried with Clang, GCC and MSVC and I obtain the same result.
CodePudding user response:
With
IntPointerWrapper bar()
{
IntPointerWrapper q;
return q;
}
you have a copy operation to copy q
into the return object of the function. That is your first copy. Then you have
IntPointerWrapper m = bar();
which copies the returned value from bar()
into m
, so that is your second copy operation.
It should be noted that the two copies only happens before C 17. Since C 17 we have guaranteed copy elision and that gets rid of the copy that happens in IntPointerWrapper m = bar();
and only has a copy for the returned object. You can see that difference in this live example