将 class 与 unique_ptr 交换
Swapping class with unique_ptr
#include <memory>
#include <algorithm>
using namespace std;
class A {
public:
unique_ptr<int> u;
A(){}
A(const A& other): u(new int(*other.u)){} // If I comment this out, it works.
// A(A&&){} // This does not help.
};
int main() {
A a;
A b = a;
swap(a, b);
}
此代码无效 - 失败并出现一大堆模板错误 no matching function for call to ‘swap(A&, A&)’
。为什么?删除第二个构造函数有帮助,但我在其他代码中需要它。我猜它可能与定义其他构造函数时自动删除某些构造函数有关,但手动添加移动构造函数也无济于事。我该如何解决这个问题?
std::swap()
要求它的参数是 move-constructible 和 move-assignable.
鉴于:
struct A {
unique_ptr<int> u;
A();
};
由于隐式定义的移动构造函数和移动赋值运算符,A
是可交换的。
但是,鉴于:
struct A {
unique_ptr<int> u;
A();
A(A const&);
};
通过声明用户定义的复制构造函数,您将禁止 A
的移动构造函数和移动赋值运算符的隐式定义
(并且通过拥有一个不可分配的可复制成员,您将禁止隐式生成 A
的复制构造函数和复制赋值运算符)。
要使 A
再次可交换,您需要用户定义 both (*):
struct A {
unique_ptr<int> u;
A();
A(A const&);
A(A&&);
A& operator=(A&&);
};
或两者都不是,只需添加适当的复制分配:
struct A {
unique_ptr<int> u;
A();
A(A const&);
A& operator=(A const&);
};
但是,这可能会破坏您避免交换深度复制的初衷,因此您最终可能会定义所有这些。
(*) noexcept 为简洁起见省略规格 ...
#include <memory>
#include <algorithm>
using namespace std;
class A {
public:
unique_ptr<int> u;
A(){}
A(const A& other): u(new int(*other.u)){} // If I comment this out, it works.
// A(A&&){} // This does not help.
};
int main() {
A a;
A b = a;
swap(a, b);
}
此代码无效 - 失败并出现一大堆模板错误 no matching function for call to ‘swap(A&, A&)’
。为什么?删除第二个构造函数有帮助,但我在其他代码中需要它。我猜它可能与定义其他构造函数时自动删除某些构造函数有关,但手动添加移动构造函数也无济于事。我该如何解决这个问题?
std::swap()
要求它的参数是 move-constructible 和 move-assignable.
鉴于:
struct A {
unique_ptr<int> u;
A();
};
由于隐式定义的移动构造函数和移动赋值运算符,A
是可交换的。
但是,鉴于:
struct A {
unique_ptr<int> u;
A();
A(A const&);
};
通过声明用户定义的复制构造函数,您将禁止 A
的移动构造函数和移动赋值运算符的隐式定义
(并且通过拥有一个不可分配的可复制成员,您将禁止隐式生成 A
的复制构造函数和复制赋值运算符)。
要使 A
再次可交换,您需要用户定义 both (*):
struct A {
unique_ptr<int> u;
A();
A(A const&);
A(A&&);
A& operator=(A&&);
};
或两者都不是,只需添加适当的复制分配:
struct A {
unique_ptr<int> u;
A();
A(A const&);
A& operator=(A const&);
};
但是,这可能会破坏您避免交换深度复制的初衷,因此您最终可能会定义所有这些。
(*) noexcept 为简洁起见省略规格 ...