Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么C++;11移动运算符(=)行为不同_C++_C++11_Move_C++14_Perfect Forwarding - Fatal编程技术网

C++ 为什么C++;11移动运算符(=)行为不同

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 &

我已经在C++11中测试了移动语义。我用move构造函数编写了一个类

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不能等同于
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;/*错误*/