移动 ctor 未启动

Moving ctor not kicking-in

以下代码

#include <iostream>

class C
{
public:
    C(int i) : i{i}{ }
    C(const C&) = delete;  // no copy allowed
    C(C&& c){ std::cout << "moving from " << c.i << '\n'; i = c.i--; }
    int i;
};

void func(C&& c) { std::cout << "func c " << c.i << '\n'; }

int main()
{
    C c{123};
    func(std::move(c));
    std::cout << "c " << c.i;
}

产出

func c 123
c 123

所以移动 ctor 没有启动:为什么?

附加问题:给出

void func(C&& c1, C&& c2) { ... }

使用相同的参数调用两次是否合法?

func(std::move(c), std::move(c));

我会说不,因为独立于首先评估哪个参数,在评估另一个参数时移动不应该是合法的。但是:

void func(C&& c1, C&& c2) { std::cout << "func c1 " << c1.i << "  c2 " << c2.i << '\n'; }

int main()
{
    C c{123};
    func(std::move(c), std::move(c));
    std::cout << "c " << c.i;
}

产出

func c1 123  c2 123
c 123

所以 moving ctor 不会再次启动。

std::move 实际上并没有调用移动构造函数。它是对 r 值引用的转换(类似于 static_cast<C&&>(c))。完成此操作后,如果您尝试复制该对象,它将调用移动构造函数或移动赋值运算符。如果您不尝试复制该对象,则什么也不会发生。试试这个:

// By value
void func(C c) { std::cout << "func c " << c.i << '\n'; }

// By r-value reference
void func2(C&& c)
{
    C c1{std::move(c)};
    std::cout << "func2 c " << c.i << '\n';
}

int main()
{
    C c{123};
    func(std::move(c));
    func2(std::move(c));
    std::cout << "c " << c.i;
}