C++ 为什么C++;11移动运算符(=)行为不同
我已经在C++11中测试了移动语义。我用move构造函数编写了一个类C++ 为什么C++;11移动运算符(=)行为不同,c++,c++11,move,c++14,perfect-forwarding,C++,C++11,Move,C++14,Perfect Forwarding,我已经在C++11中测试了移动语义。我用move构造函数编写了一个类 class DefaultConstructor { public: DefaultConstructor(std::vector<int> test) : m_vec(std::forward<std::vector<int>>(test)) { }; DefaultConstructor(DefaultConstructor &
class DefaultConstructor
{
public:
DefaultConstructor(std::vector<int> test) :
m_vec(std::forward<std::vector<int>>(test))
{
};
DefaultConstructor(DefaultConstructor &&def) :
m_vec(std::forward<std::vector<int>>(def.m_vec))
{
}
DefaultConstructor& operator=(DefaultConstructor&& def) {
m_vec = std::move(def.m_vec);
return *this;
}
DefaultConstructor& operator=(const DefaultConstructor&) = delete;
DefaultConstructor(DefaultConstructor &) = delete;
std::vector<int> m_vec;
};
int main()
{
std::vector<int> test = { 1, 2, 3, 4, 5 };
DefaultConstructor testConstructor(std::move(test));
DefaultConstructor testConstructor2 = std::move(testConstructor);
DefaultConstructor &testConstructor3 = DefaultConstructor({ 6, 7, 8, 9 });
DefaultConstructor testConstructor4 = std::move(testConstructor3);
swapMove(testConstructor, testConstructor2);
}
好吧,我想也许不再需要=Move操作符了。但我尝试了SwapMove函数。此函数调用=移动运算符
template<typename T>
void swapMove(T &a, T &b)
{
T tmp(std::move(a));
a = std::move(b);
b = std::move(tmp);
}
模板
无效swapMove(T&a、T&b)
{
T tmp(std::move(a));
a=标准::移动(b);
b=标准::移动(tmp);
}
有人能解释一下这两个电话的区别吗?不应该是调用
a=std::move(b)代码>和DefaultConstructor testConstructor2=std::move(testConstructor)代码>具有相同的行为?默认构造函数testConstructor2=std::move(testConstructor)代码>是构造,不是赋值。这与C++11之前相同类型的代码中的复制构造与赋值完全类似。语法
DefaultConstructor testConstructor2 = something;
始终调用构造函数,因为对象testConstructor2
尚不存在。运算符=只能在已构造的对象的上下文中调用。此:
T foo = bar;
被称为。它通常(但并非总是)等同于:
T foo(bar);
区别在于后者是对T
构造函数的直接函数调用,而前者试图构造从decltype(bar)
到T
的隐式转换序列。因此,在某些情况下,直接初始化成功,但复制初始化可能失败。无论哪种方式,初始化都是初始化:它是构造函数调用,而不是赋值调用
但在我们的例子中,这两条线是完全等效的:
DefaultConstructor testConstructor2 = std::move(testConstructor);
DefaultConstructor testConstructor2{std::move(testConstructor)};
它们都不调用DefaultConstructor::operator=
DefaultConstructor testConstructor2=std::move(testConstructor)代码>是初始化,而不是赋值。事先单独声明testConstructor2
,例如defaultconstructortestconstructor2({})代码>乔纳森·波特看起来这就是答案。Thx。[OT]您希望在移动构造函数中使用std::move()
,而不是std::forward()
。没有什么可决定的,您已经明确说过def
是一个右值引用std::forward
仅在使用模板+引用折叠时有用。只是出于好奇,何时将T foo=bar当需要多次转换时,code>不能等同于T foo(bar)
?@PCLuddite。e、 g.:结构A{A(int){};结构B{B(A){}给定,bb(4)代码>成功,但B=4
不会。@PCLuddite也可以在您有一个更好匹配的显式构造函数(或唯一可能的匹配,这使得=
案例成为错误)时进行<代码>结构A{显式A(bool){/*#1*/}A(int){/*#2*/}};A=真;/*调用#2*/ab(false);/*调用#1*/
并且当所讨论的类不可复制/可移动时:struct B{B(B&&)=delete;B(int){};B(1);/*OK*/B b2=1;/*错误*/