我最近一直在研究右值参考,并得出一个结论,即在任何地方使用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
即使没有提示也不会在其生命周期结束时使用额外的副本来惩罚我。实际上,即使在复杂的函数中,编译器也应该能够识别它。
问题:
C ++ 0x Standard是否允许此优化?
编译器是否使用它?即使在复杂的情况下,即函数由多行组成?
这种优化的可靠性如何,即我希望编译器能够像我期望编译器应用返回值优化那样使用它吗?
答案 0 :(得分:17)
C ++ 0x Standard是否允许这种优化?
没有
编译器是否使用它?即使在 复杂的情况,即功能 是由多行组成的?
没有
此优化的可靠性如何, 即我可以期待编译器 尽可能多地利用它 编译器应用返回值 优化
您应该使用print语句装饰A(const A&)
和A(A&&)
并运行您感兴趣的测试用例。如果这些用例是您设计的一部分,请不要忘记测试左值参数。
正确的答案将取决于A
的复制和移动的费用,Object::value
实际有多少参数,以及您愿意忍受多少代码重复。
最后,非常可疑包含“始终”或“无处不在”等字词的任何指南。例如。我偶尔会使用goto
。但是其他程序员有像“永远”这样的词与goto
相关联。但每隔一段时间,你就无法在速度和清晰度方面击败goto
。
有时您应该支持foo(const A&) foo(A&&)
对foo(A)
。有时候你不会。您对装饰副本和移动成员的实验将指导您。