Reputation: 80
I am learning about copy elision and tried out something to learn about it. But there is something unexpected happening with the below code:
template<typename T>
class AutoPtr
{
T* m_ref;
public:
AutoPtr(T* ref)
{
printf("Cons called\n");
m_ref = ref;
}
AutoPtr(const AutoPtr& autoPtr)
{
printf("Copy called\n");
m_ref = autoPtr.m_ref;
}
~AutoPtr()
{
delete m_ref;
}
};
class Reference
{
public:
Reference()
{
printf("Reference created\n");
}
~Reference()
{
printf("Reference deleted\n");
}
};
AutoPtr<Reference> generateRes()
{
Reference *ref = new Reference();
//Scenario 1
//AutoPtr<Reference> temp{ref};
//return temp;
//Scenario 2
return AutoPtr<Reference>{ref};
}
int main()
{
AutoPtr<Reference> obj1 = generateRes();
return 0;
}
In the above code, I am trying 2 scenarios.
Why doesn't scenario 1 call constructor for obj1? Is it some compiler optimization? I know that copy elision has happened and copy constructor is not called, but why is the normal constructor not called twice?
Upvotes: 0
Views: 91
Reputation: 801
I guess the part you missed about copy elision is what it implies. If no copy-construction takes place, what does the new (caller-side) object get constructed from?
No copying (or moving) implies there is only one object. That means construction is done right at the destination, i.e. constructing the return value inside the function == constructing the returned value outside.
This has also nothing to do with your copy-assignment operator AutoPtr operator=(const AutoPtr&)
, since AutoPtr<Reference> obj1 = generateRes();
is an initialization.
Upvotes: 2