27

我最近一直在研究右值引用并得出一个结论,即在将制作对象的完整副本的任何地方都使用按值传递是非常有利的(有关完整的理由,请参见例如如何在添加右值引用运算符时减少冗余代码重载?想要速度?按值传递!),因为编译器可以在诸如f(std::move(a));, where fis defined as的情况下自动优化一个副本void f(A a);

pass-by-value-everywhere 的一个负面后果是,std::move即使在简单的情况下,所有代码也会变得乱七八糟,例如:

void Object::value(A a) 
{
    value_ = std::move(a);
}

显然,如果我只写以下内容:

void Object::value(A a) 
{
    value_ = a;
}

即使没有提示也不应该用额外的副本惩罚我,编译器应该不难识别它a接近其生命周期的尽头。事实上,即使在复杂的函数中,编译器也应该能够识别这一点。

问题:

  1. C++0x 标准是否允许这种优化?

  2. 编译器是否使用它?即使在复杂的情况下,即功能由不止一行组成?

  3. 这种优化有多可靠,即我可以期望编译器像我期望编译器应用返回值优化一样多地利用它吗?

4

1 回答 1

20

C++0x 标准是否允许这种优化?

不。

编译器是否使用它?即使在复杂的情况下,即功能由不止一行组成?

不。

这种优化有多可靠,即我可以期望编译器像我期望编译器应用返回值优化一样多地利用它吗?

您应该装饰A(const A&)A(A&&)使用打印语句并运行您感兴趣的测试用例。如果这些用例是您设计的一部分,请不要忘记测试左值参数。

正确答案取决于复制和移动的成本、实际有A多少参数Object::value以及您愿意忍受多少代码重复。

最后,对任何包含“总是”或“无处不在”等词的指南要非常怀疑。例如,我goto每隔一段时间使用一次。但是其他程序员有类似“从不”这样的词与goto. 但是每隔一段时间,你就无法goto在速度和清晰度上击败一个。

There will be times you should favor a pair of foo(const A&) foo(A&&) over foo(A). And times you won't. Your experiments with decorated copy and move members will guide you.

于 2011-05-22T17:31:27.873 回答