C++ moving constructor – A tour of C++


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?

>Solution :

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.

Leave a Reply Cancel reply