在移动运算符/赋值运算符中,我应该使用std::move还是std::forward
Should I use std::move or std::forward in move ctors/assignment operators?
除非我错了,否则两者似乎都很好用——有没有最好的实践理由来选择其中一个?
示例:
struct A
{
A(){}
A(const A&){ std::cout << "A(const A&)n"; }
A(A&&){ std::cout << "A(A&&)n"; }
};
struct B
{
B(){}
B(const B& right) : x(right.x){ std::cout << "B(const B&)n"; }
B(B&& right) : x(std::forward<A>(right.x)){ std::cout << "B(B&&)n"; }
A x;
};
struct C
{
C(){}
C(const C& right) : x(right.x){ std::cout << "C(const C&)n"; }
C(C&& right) : x(std::move(right.x)){ std::cout << "C(C&&)n"; }
A x;
};
struct D
{
D(){}
D(const D& right) : x(right.x){ std::cout << "D(const D&)n"; }
D(D&& right) : x(right.x){ std::cout << "D(D&&)n"; }
A x;
};
int main()
{
std::cout << "--- B Test ---n";
B b1;
B b2(std::move(b1));
std::cout << "--- C Test ---n";
C c1;
C c2(std::move(c1));
std::cout << "--- D Test ---n";
D d1;
D d2(std::move(d1));
}
输出:
--- B Test ---
A(A&&)
B(B&&)
--- C Test ---
A(A&&)
C(C&&)
--- D Test ---
A(const A&)
D(D&&)
问题是:这些真的是类的移动构造函数/赋值运算符吗还是它们只是从你的眼角看起来像那样
struct X{
X(X&&); // move ctor #1
template<class T>
X(T&&); // perfect forwarding ctor #2
X& operator=(X&&); // move assignment operator #3
template<class T>
X& operator=(T&&); // perfect forwarding ass. operator #4
};
在实际移动操作符(#1)和移动赋值操作符(#3)中,您永远不会使用std::forward
,因为如果您正确评估,您将始终移动。
注意,如果没有完美的转发模板(T&&
),std::forward
就没有意义。这正是#2和#4的情况。在这里,你永远不会使用std::move
,因为你不知道你是否真的得到了一个右值(A-OK)或一个左值(不那么多)。
请参阅我的答案,了解std::forward
的实际工作原理。
相关文章:
- Usages of std::move
- 在C++中对T*类型执行std::move的意外行为
- 关于std::move的使用,是否有编译警告
- 我应该实现右值推送功能吗?我应该使用std::move吗
- 通过实例理解std::move及其目的
- 返回一个带有 std::move 的对象并链接函数
- 当 std::move 与 C 样式数组或不移动对象时会发生什么
- std::move a const std::vector in a lambda capture
- "std::forward"和"std::move"真的不生成代码吗?
- 如何在没有 std::move 的情况下移动临时对象
- 关于在成员重载中使用 std::move() 的问题
- 显式清除 std::move 之后的源资源
- std::move 如何使原始变量的值无效?
- 复制elision、std::move和链式函数调用
- 如果真的需要std::move,我们应该什么时候声明右值refs
- 使用std::move将std::unique_ptr作为qt信号参数传递
- 无法使用带有 std::move 的自定义删除器插入 std::unique_ptr
- C++:我应该在 return 语句中显式使用 std::move() 来强制移动吗?
- 编译器是否足够聪明,以至于 std::move 变量超出范围?
- std::move() 或其在局部变量上的显式等价物可以允许 elision 吗?