我应该使用std :: move或std :: forward在移动ctors /赋值运算符? [英] Should I use std::move or std::forward in move ctors/assignment operators?
问题描述
除非我错了似乎要么工作正常 - 是否有一个最佳实践的理由喜欢一个比另一个?
示例:
struct A
{
A(){}
A(const A&){std :: cout < A(const A&)\\\
; }
A(A&&){std :: cout<< A(A&&)\\\
; }
};
struct B
{
B(){}
B(const B& right):x(right.x){std :: cout< ; B(const B&)\\\
; }
B(B&& right):x(std :: forward< A>(right.x)){std :: cout< B(B&&)\\\
; }
A x;
};
struct C
{
C(){}
C(const C& right):x(right.x){std :: cout< ; C(const C&)\\\
; }
C(C&& right):x(std :: move(right.x)){std :: cout< C(&&)\\\
; }
A x;
};
struct D
{
D(){}
D(const D& right):x(right.x){std :: cout< ; D(const D&)\\\
; }
D(D&& right):x(right.x){std :: cout< D(D&&)\\\
; }
A x;
};
int main()
{
std :: cout< --- B Test --- \\\
;
B b1;
B b2(std :: move(b1));
std :: cout<< --- C Test --- \\\
;
C c1;
C c2(std :: move(c1));
std :: cout<< --- D Test --- \\\
;
D d1;
D d2(std :: move(d1));
}
输出:
p $ p>
--- B测试---
A(A&&)
B(B& -
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&&;); //完美的转发屁股。运算符#4
};
在真实 move ctor(#1)和移动赋值运算符#3),你永远不会使用 std :: forward
,因为,如你正确评估,你将永远移动。
请注意,如果没有完美的转发模板( T&&
), std :: forward
这正是#2和#4的情况。在这里,你永远不会使用 std :: move
,因为你不知道实际上是否有一个右值(A-OK)或左值(不是那么多)。
请参阅我的这个答案,了解如何 std :: forward
实际上可以工作。
Unless I'm wrong it seems like either works just fine - is there a best practice reason to prefer one over the other?
Example:
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));
}
Output:
--- B Test ---
A(A&&)
B(B&&)
--- C Test ---
A(A&&)
C(C&&)
--- D Test ---
A(const A&)
D(D&&)
解决方案 The question is: Are those really the move constructor / assignment operator for the class? Or do they only look like that from the corner of your eye?
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
};
In a real move ctor (#1) and move assignment operator (#3), you will never use std::forward
, since, as you correctly assessed, you will always move.
Note that std::forward
never makes sense without a perfect forwarding template (T&&
). That is exactly the case for #2 and #4. Here, you will never use std::move
, since you don't know if you actually got an rvalue (A-OK) or an lvalue (not so much).
See this answer of mine for an explanation of how std::forward
actually works.
这篇关于我应该使用std :: move或std :: forward在移动ctors /赋值运算符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!