【问题标题】:What rules to follow for a function to use NRV optimization函数使用 NRV 优化应遵循哪些规则
【发布时间】:2011-05-07 09:06:49
【问题描述】:

我应该遵循哪些规则或提示来使函数能够在函数中使用 NRV(命名返回值)优化?我从不同地方吸收了这些技巧,但不知道我的理解是否正确:

  1. 要返回的对象在函数内部不应该有任何名字(那为什么叫NAMED返回值优化!!)
  2. return 语句的对象应该用括号括起来
  3. 要返回的对象应具有显式和内联的复制构造函数

【问题讨论】:

  • 我回答了你关于1(这似乎是重点),但我并没有真正理解2,我不确定3,但我认为编译器不在乎关于复制构造函数是内联并显式定义的(它可能不应该有显式关键字,因为如果没有优化发生,它需要被隐式调用)。

标签: c++


【解决方案1】:

如果您的意思是 NRVO(命名返回值优化)而不是 RVO(返回值优化),那么对象必须在函数内部命名。否则,它将仅符合 RVO 资格,而不是 NRVO。因此,将其称为命名返回值优化是有充分理由的。

查看以下示例:

RVO:

BigObject foo(int x, int y)
{
    // Returned BigObject is created ad-hoc, and has no local 'name'.
    return BigObject(x, y);
}

void bar()
{
    BigObject obj = foo(4, 6);
}

会被优化编译器翻译成这个伪代码:

void foo(int x, int y, BigObject& ret)
{
    ret._constructor_(x, y);
}

void bar()
{
    BigObject obj; // Allocate obj on the stack, but don't construct it just yet!
    foo(4, 6, obj); // Now obj is constructed by foo()
}

NRVO:

BigObject foo(int x, int y, int z)
{
    // Returned BigObject has a local 'name' in foo(), which is obj.
    BigObject obj(x, y);

    // Do something with obj
    obj.setZ(z);

    return obj;
}

void bar()
{
    BigObject obj = foo(4, 6, 7);
}

会被优化编译器翻译成这个伪代码:

void foo(int x, int y, int z, BigObject& ret)
{
    ret._constructor_(x, y);

    // Do something with ret
    ret.setZ(z);
}

void bar()
{
    BigObject obj; // Allocate obj on the stack, but don't construct it just yet!
    foo(4, 6, 7, obj); // Now obj is constructed by foo()
}

请注意,优化是否实际发生在很大程度上取决于编译器。一些编译器(如非常老的编译器)根本不会执行 RVO 或 NRVO,而其他编译器可能对此优化有不同的限制。下面是 MSVC 对 NRVO 的约束的描述: http://msdn.microsoft.com/en-us/library/ms364057(v=vs.80).aspx#nrvo_cpp05_topic3

【讨论】:

  • 啊啊!我误以为 RVO 是 NRVO 的缩写形式
  • 没有。两者都是由编译器完成的,用户根本无法控制它们。 NRVO 在对象在返回函数中具有“本地名称”时完成,而 RVO 在与 return 语句在同一行创建时完成。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-14
  • 2021-10-22
  • 1970-01-01
  • 1970-01-01
  • 2016-10-23
  • 1970-01-01
相关资源
最近更新 更多