返回值优化

返回值优化

在以下几种情况中,编译器可能会省略对象的拷贝和移动操作。对象直接在原本拷贝/移动的内存中直接构造对象。当发生这种优化时,虽然拷贝/移动构造函数没有调用,但是拷贝/移动构造函数必须是可访问的,否则程序是错误的。

  • return语句中,当操作数是拥有自动存储期,命名的对象时,且该操作数不是函数参数和catch语句的参数,并且该操作数的类型与函数的返回类型一致。这种优化被称为NRVO(named return value optimization)
  • 在对象的初始化中,当源对象是一个未命名的临时量,且该临时量与目标对象拥有相同的类型。当该未命名的临时量作为return语句的操作数时,这种优化被称为RVO(return value optimization)
  • throw表达式中,当操作数是一个拥有自动存储期,非volatile的对象,且该操作数不是函数的参数,不是catch语句的参数,并且这个该操作数的范围不超过最内部的try块。
  • catch语句中,当参数与抛出的异常对象类型一致时,异常对象的拷贝将会被省略,catch语句的主体可以直接访问到异常对象。
  • 在常量表达式和常量初始化中,允许return value optimization(RVO),禁止named return value optimization(NRVO)
struct A {
    void *p;
    constexpr A(): p(this) {}
};
 
constexpr A g()
{
    A a;
    return a;
}
 
constexpr A a;          // a.p points to a
// constexpr A b = g(); //b.p将会空悬,因为指向了一个临时量
 
void h()
{						
    A c = g();          // c.p 可能指向c或者一个临时量
}
 
extern const A d; 
constexpr A f()
{
    A e;
    if (&e == &d)
        return A();
    else
        return e;
    // 在常量环境下,强制执行NRVO会导致冲突
    // 在非常量环境下,才会执行NRVO
} 
// constexpr A d = f(); // d.p将会空悬

例子

#include <iostream>
#include <vector>
 
struct Noisy {
    Noisy() { std::cout << "constructed at " << this << '\n'; }
    Noisy(const Noisy&) { std::cout << "copy-constructed\n"; }
    Noisy(Noisy&&) { std::cout << "move-constructed\n"; }
    ~Noisy() { std::cout << "destructed at " << this << '\n'; }
};
 
std::vector<Noisy> f() {
    std::vector<Noisy> v = std::vector<Noisy>(3); //临时量初始化v发生拷贝省略
                                                  
    return v; // 执行NRVO优化
}             // 如果不能执行NRVO优化,则调用移动构造函数
 
void g(std::vector<Noisy> arg) {
    std::cout << "arg.size() = " << arg.size() << '\n';
}
 
int main() {
    std::vector<Noisy> v = f(); // copy elision in initialization of v
                                // from the temporary returned by f() (until C++17)
                                // from the prvalue f() (since C++17)
    g(f());                     //函数g()参数初始化发生拷贝省略操作
                                
}

输出

constructed at 0x2145c20
constructed at 0x2145c21
constructed at 0x2145c22
constructed at 0x2146c50
constructed at 0x2146c51
constructed at 0x2146c52
arg.size() = 3
destructed at 0x2146c50
destructed at 0x2146c51
destructed at 0x2146c52
destructed at 0x2145c20
destructed at 0x2145c21
destructed at 0x2145c22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值