8

一段时间以来,我们可以听到很多关于值语义在 C++ 中非常重要的信息(即此处此处)。我知道我们应该使用它,尤其是当我们打算复制函数体内的值时。所以我认为这样的用法是公平的:

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++ 中的许多情况一样,这取决于(即特定类型的复制和移动成本)?:-)

4

2 回答 2

1

一般来说,它取决于特定类型(甚至对象)的复制和移动成本以及它的调用方式(是否使用临时对象等)

例如临时boo(gimme_t())

d是你的类树的深度

成本为 的解决方案,move成本为 的d * COST_OF_MOVE解决方案COST_OF_COPY + d * REF_ASSIGNMENT

你可以看到,对于std::string它的O(d)vs O(n)so,对于大长度的字符串,使用移动更便宜(对于短字符串,它并不那么重要),但对于std::array<int>它是O(nd)vs O(n + d),所以你最好使用一个副本。

但如果参数不是临时的 ( T t; boo(t)) 成本将是:

COST_OF_COPY + d * COST_OF_MOVEvs COST_OF_COPY + d * REF_ASSIGNMENT,因此 const-ref 解决方案的d移动速度更快。

但是,如果您可能考虑move几乎免费™,您最好使用移动解决方案以避免 1 副本以防临时参数


(*) 你应该阅读的所有地方,d ± 1而不是d

于 2013-08-11T18:19:54.053 回答
0

对于模板和类似模板的解决方案,您显然应该使用完美的转发。foo(MyType copy)在其他情况下,通过声明强制复制似乎很棘手。避免成本,并在必要时复制,即使通过复制省略编译器可能比移动操作更有效。

于 2013-08-11T17:11:54.203 回答