I'm trying to understand section 4.6.2 of the book where move constructor and move assignment are introduced.
The way I understand it, the goal is to avoid a stack allocated vector to be needlessly copied (I'm speculating... on the heap or directly the call stack of the caller) before returning it to the caller. The code looks like so:
Vector operator (const Vector& a, const Vector& b) {
if (a.size() != b.size())
throw length_error {"Vectors must be the same size"};
Vector res(a.size());
for (int i = 0; i < res.size(); i )
res[i] = a[i] b[i];
return res;
}
Here's my usage:
int main() {
Vector v1 {8,8,9};
Vector v3 = v1 v1 v1 v1;
cout << v3 << endl;
}
I have traces in my destructors and I would expect, without the usage of moving constructor/assignments, there to be additional destruction of the res
local in operator .
However there isn't, there is only one destruction that occurs on the subresult v1 v1 at the end of the program (this destruction has to occur since v1 v1 exists at a point in the program), one on the subresult of the former v1, and then another one for the last v1.
Also, implementing the moving constructor/assignment reveals that those are never called.
Why do I not see two destruction for each of the subresult without the moving constructor and why are my moving constructor not called when implemented?
CodePudding user response:
I would wager that this is the result of copy elision. In short, the compiler is allowed to omit calling the copy/move constructors, even if they have side effects. So you cannot count on them being called
Relevant part from the reference says
Under the following circumstances, the compilers are required to omit the copy and move construction of class objects, even if the copy/move constructor and the destructor have observable side-effects. The objects are constructed directly into the storage where they would otherwise be copied/moved to.
Copy elision is an exception to the as-if rule, where compilers are only allowed to do optimizations that preserve the old behavior.