Move or Named Return Value Optimization (NRVO)?

The compiler may NRVO into a temp space, or move construct into a temp space. From there it will move assign x.

Update:

Any time you’re tempted to optimize with rvalue references, and you’re not positive of the results, create yourself an example class that keeps track of its state:

  • constructed
  • default constructed
  • moved from
  • destructed

And run that class through your test. For example:

#include <iostream>
#include <cassert>

class A
{
    int state_;
public:
    enum {destructed = -2, moved_from, default_constructed};

    A() : state_(default_constructed) {}
    A(const A& a) : state_(a.state_) {}
    A& operator=(const A& a) {state_ = a.state_; return *this;}
    A(A&& a) : state_(a.state_) {a.state_ = moved_from;}
    A& operator=(A&& a)
        {state_ = a.state_; a.state_ = moved_from; return *this;}
    ~A() {state_ = destructed;}

    explicit A(int s) : state_(s) {assert(state_ > default_constructed);}

    friend
    std::ostream&
    operator<<(std::ostream& os, const A& a)
    {
        switch (a.state_)
        {
        case A::destructed:
            os << "A is destructed\n";
            break;
        case A::moved_from:
            os << "A is moved from\n";
            break;
        case A::default_constructed:
            os << "A is default constructed\n";
            break;
        default:
            os << "A = " << a.state_ << '\n';
            break;
        }
        return os;
    }

    friend bool operator==(const A& x, const A& y)
        {return x.state_ == y.state_;}
    friend bool operator<(const A& x, const A& y)
        {return x.state_ < y.state_;}
};

A&& f()
{
    A y;
    return std::move(y);
}

int main()
{
    A a = f();
    std::cout << a;
}

If it helps, put print statements in the special members that you’re interested in (e.g. copy constructor, move constructor, etc.).

Btw, if this segfaults on you, don’t worry. It segfaults for me too. Thus this particular design (returning an rvalue reference to a local variable) is not a good design. On your system, instead of segfaulting, it may print out “A is destructed”. This would be another sign that you don’t want to do this.

Leave a Comment