【发布时间】:2021-09-17 18:41:57
【问题描述】:
最近,我发现自己经常遇到将某个对象作为参数的单个函数的情况。该函数必须复制该对象。
但是,该函数的参数也可能经常是临时参数,因此我还想提供该函数的重载,该函数采用右值引用而不是 const 引用。
这两种重载的区别仅在于它们具有不同类型的引用作为参数类型。除此之外,它们在功能上是等效的。
例如考虑这个玩具示例:
void foo(const MyObject &obj) {
globalVec.push_back(obj); // Makes copy
}
void foo(MyObject &&obj) {
globalVec.push_back(std::move(obj)); // Moves
}
现在我想知道是否有办法避免这种代码重复,例如根据另一个功能实现一个功能。
例如,我正在考虑按照这样的 move-one 来实现复制版本:
void foo(const MyObject &obj) {
MyObj copy = obj;
foo(std::move(copy));
}
void foo(MyObject &&obj) {
globalVec.push_back(std::move(obj)); // Moves
}
但这似乎仍然不理想,因为现在调用 const ref 重载时会发生复制和移动操作,而不是之前需要的单个复制操作。
此外,如果对象不提供移动构造函数,那么这将有效地复制对象两次(afaik),这会破坏首先提供这些重载的整个目的(尽可能避免复制)。
我确信可以使用宏和预处理器一起破解某些东西,但我非常希望避免让预处理器参与其中(出于可读性目的)。
因此我的问题是:是否有可能实现我想要的(实际上只实现一次功能,然后根据第一个重载实现第二个重载)?
如果可能的话,我想避免使用模板。
【问题讨论】:
-
应该是
globalVec.push_back(std::move(obj)); // Moves。 -
void foo(MyObject obj) { globalVec.push_back(std::move(obj)); }可以避免过载。 -
啊,是的,我忘了在我的例子中写明确的
std::move。 -
只要你给一个右值一个名字,它就会变成一个 lvaue 所以
obj在这一行globalVec.push_back(std::move(obj)); // Moves是一个 lvaue 并且不会移动到向量中 -
你可能对我的桌子感兴趣here
标签: c++ c++11 move-semantics rvalue-reference perfect-forwarding