"Defaulted" 移动构造函数和赋值 - 奇怪的行为
"Defaulted" move constructor and assignment - weird behaviour
所以我有一个 class 的简单示例,它有两个成员变量。我已经声明了一个副本和一个移动构造函数,它们是 = default
,这将强制编译器为我生成它们。现在我的问题是这个。使用移动构造函数(或赋值)时,为什么我移动的对象保持不变?
例如,如果我有:
myclass obj(4, 5);
myclass obj2 = std::move(4, 5);
据我了解,在第二行 obj
之后将包含 "nothing",因为它将被移动到 obj2
中,其值将是 (4, 5)
。我知道我不是用来纠正这里的术语....
完整代码:
#include <iostream>
#include <utility>
template<class T1, class T2>
class Pair
{
public:
T1 first;
T2 second;
public:
//CONSTRUCTORS
constexpr Pair() = default;
constexpr Pair(const T1& _first, const T2& _second)
: first(_first), second(_second)
{}
constexpr Pair(T1&& _first, T2&& _second)
: first(std::forward<T1>(_first)), second(std::forward<T2>(_second))
{}
constexpr Pair(const Pair&) = default;
constexpr Pair(Pair&&) = default;
//ASSIGNMENT
Pair &operator=(const Pair&) = default;
Pair &operator=(Pair&&) = default;
};
int main()
{
Pair<int, int> p(1, 2);
Pair<int, int> p2 = p; //all good, p = {1, 2} and p2 = {1, 2}
Pair<int, int> p3 = std::move(p); //p = {1, 2} and p3 = {1, 2}
//why isn't p "moved" into p3??
//p should be empty??
//same thing occurs with the move assignment. why?
std::cout << p.first << " " << p.second << "\n";
std::cout << p2.first << " " << p2.second << "\n";
std::cout << p3.first << " " << p3.second << "\n";
}
int
的默认移动只是复制。
默认的移动构造函数和移动赋值将简单地向所有成员调用 std::move
。和拷贝一样,默认的拷贝构造函数简单调用所有成员的拷贝。
你的代码是正确的,调用std::move
后,移动的数据仍然存在是正常的。为什么?因为 std::move
on primitive 复制了它们。编译器不会生成将 move int 移至 0
的代码,因此它是一个简单的副本。但是,如果你的 pair 包含更复杂的类型,例如 std::vector<int>
,移动的向量实际上将变为空。
所以我有一个 class 的简单示例,它有两个成员变量。我已经声明了一个副本和一个移动构造函数,它们是 = default
,这将强制编译器为我生成它们。现在我的问题是这个。使用移动构造函数(或赋值)时,为什么我移动的对象保持不变?
例如,如果我有:
myclass obj(4, 5);
myclass obj2 = std::move(4, 5);
据我了解,在第二行 obj
之后将包含 "nothing",因为它将被移动到 obj2
中,其值将是 (4, 5)
。我知道我不是用来纠正这里的术语....
完整代码:
#include <iostream>
#include <utility>
template<class T1, class T2>
class Pair
{
public:
T1 first;
T2 second;
public:
//CONSTRUCTORS
constexpr Pair() = default;
constexpr Pair(const T1& _first, const T2& _second)
: first(_first), second(_second)
{}
constexpr Pair(T1&& _first, T2&& _second)
: first(std::forward<T1>(_first)), second(std::forward<T2>(_second))
{}
constexpr Pair(const Pair&) = default;
constexpr Pair(Pair&&) = default;
//ASSIGNMENT
Pair &operator=(const Pair&) = default;
Pair &operator=(Pair&&) = default;
};
int main()
{
Pair<int, int> p(1, 2);
Pair<int, int> p2 = p; //all good, p = {1, 2} and p2 = {1, 2}
Pair<int, int> p3 = std::move(p); //p = {1, 2} and p3 = {1, 2}
//why isn't p "moved" into p3??
//p should be empty??
//same thing occurs with the move assignment. why?
std::cout << p.first << " " << p.second << "\n";
std::cout << p2.first << " " << p2.second << "\n";
std::cout << p3.first << " " << p3.second << "\n";
}
int
的默认移动只是复制。
默认的移动构造函数和移动赋值将简单地向所有成员调用 std::move
。和拷贝一样,默认的拷贝构造函数简单调用所有成员的拷贝。
你的代码是正确的,调用std::move
后,移动的数据仍然存在是正常的。为什么?因为 std::move
on primitive 复制了它们。编译器不会生成将 move int 移至 0
的代码,因此它是一个简单的副本。但是,如果你的 pair 包含更复杂的类型,例如 std::vector<int>
,移动的向量实际上将变为空。