从一段时间以来,我们可以听到很多关于semanthics在C ++中非常重要的价值(即here和here)。我知道我们应该使用它,特别是当我们打算复制函数体内的值时。所以我认为这样的用法是公平的:
void foo(std::string txt) { my_container.emplace_back(move(txt)); }
但是我没有找到任何建议如果我必须通过大型项目中有时会发生的大型函数树传递该参数。例如:
void bar(std::string txt) { foo(move(txt)); /* more actions */ }
void boo(std::string txt) { bar(move(txt)); /* more actions */ }
有人可以推荐在这种情况下做什么吗?我们应该保持价值语义,并希望编译器优化器能够限制移动操作的数量或在任何地方使用const引用,并且最后只有一个副本?或许,正如在许多情况下在C ++中,它取决于(即复制和移动特定类型的成本)? : - )
答案 0 :(得分:1)
一般情况下,它取决于复制和移动特定类型(甚至是对象)的成本以及它是如何被调用的(不论是否有临时性等)
例如临时boo(gimme_t())
:
让d
是您的课程树的深度
move
成本为d * COST_OF_MOVE
的解决方案,解决方案为COST_OF_COPY + d * REF_ASSIGNMENT
。
你可以看到,std::string
它是O(d)
vs O(n)
所以对于长度较大的字符串,使用移动会更便宜(对于短字符串来说,它并不那么重要),但对于{ {1}}它是std::array<int>
vs O(nd)
,因此您最好使用一份副本。
但如果参数不是临时的(O(n + d)
),则费用为:
T t; boo(t)
vs COST_OF_COPY + d * COST_OF_MOVE
,因此COST_OF_COPY + d * REF_ASSIGNMENT
移动时const-ref解决方案更快。
但如果你可以考虑d
几乎免费™,你最好使用移动解决方案,以避免在临时争论的情况下复制一份
(*)您应该在任何地方阅读move
而不是d ± 1
答案 1 :(得分:0)
对于模板和类似模板的解决方案,您显然应该完美转发。在其他情况下,通过foo(MyType copy)
声明强制复制似乎是针。避免成本,并在必要时进行复制,即使通过copy-elision,编译器可能比移动操作更有效。