当最后一次使用可移动对象时,编译器会自动使用移动语义吗?

时间:2011-05-22 17:01:42

标签: c++ optimization c++11 rvalue-reference move-semantics

我最近一直在研究右值参考,并得出一个结论,即在任何地方使用pass-by-value进行完整的对象复制是非常有利的(为了完整的理由,请参阅例如How to reduce redundant code when adding rvalue reference operator overloads?和{ {3}}),因为编译器可以在f(std::move(a));等情况下自动优化副本,其中f定义为void f(A a);

价值传递的一个负面后果是所有代码都被std::move弄得乱七八糟,即使是在以下简单情况下:

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

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

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

编译器应该很难识别出a即使没有提示也不会在其生命周期结束时使用额外的副本来惩罚我。实际上,即使在复杂的函数中,编译器也应该能够识别它。

问题:

  1. C ++ 0x Standard是否允许此优化?

  2. 编译器是否使用它?即使在复杂的情况下,即函数由多行组成?

  3. 这种优化的可靠性如何,即我希望编译器能够像我期望编译器应用返回值优化那样使用它吗?

1 个答案:

答案 0 :(得分:17)

  

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

没有

  

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

没有

  

此优化的可靠性如何,   即我可以期待编译器   尽可能多地利用它   编译器应用返回值   优化

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

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

最后,非常可疑包含“始终”或“无处不在”等字词的任何指南。例如。我偶尔会使用goto。但是其他程序员有像“永远”这样的词与goto相关联。但每隔一段时间,你就无法在速度和清晰度方面击败goto

有时您应该支持foo(const A&) foo(A&&)foo(A)。有时候你不会。您对装饰副本和移动成员的实验将指导您。