移动或命名返回值优化(NRVO)

Move or Named Return Value Optimization (NRVO)?

本文关键字:NRVO 优化 返回值 移动      更新时间:2023-10-16

假设我们有以下代码:

std::vector<int> f()
{
  std::vector<int> y;
  ...
  return y;
} 
std::vector<int> x = ...
x = f();

编译器似乎有两种方法:

(a) NRVO:破坏x,然后构造f()来代替x。
(b) 移动:在临时空间中构造f(),将f()移动到x中,析构函数f()。

根据标准,编译器是否可以自由使用任何一种方法?

编译器可以将NRVO放入临时空间,或者将构造移动到临时空间。从那里它将移动分配x

更新:

任何时候,如果您想使用右值引用进行优化,但对结果不满意,请为自己创建一个跟踪其状态的示例类:

  • 构造的
  • 默认构造
  • 从移动
  • 已销毁

并在测试中运行该类。例如:

#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 destructedn";
            break;
        case A::moved_from:
            os << "A is moved fromn";
            break;
        case A::default_constructed:
            os << "A is default constructedn";
            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;
}

如果有帮助的话,把print语句放在你感兴趣的特殊成员中(例如复制构造函数、移动构造函数等)

顺便说一句,如果这件事发生在你身上,别担心。它对我来说也是错的。因此,这种特殊的设计(返回对局部变量的右值引用)不是一个好的设计。在您的系统上,它可能会打印出"A已销毁",而不是分段故障。这将是你不想这样做的另一个迹象。