移动 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;
}
以下代码
#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;
}