如何为具有unique_ptr
成员变量的类实现复制构造函数?我只考虑C++ 11。使用unique_ptr复制类的构造函数
回答
由于unique_ptr
不能共享,你需要或者深复制其内容或转换unique_ptr
为shared_ptr
。
class A
{
std::unique_ptr<int> up_;
public:
A(int i) : up_(new int(i)) {}
A(const A& a) : up_(new int(*a.up_)) {}
};
int main()
{
A a(42);
A b = a;
}
可以作为NPE提到,使用一招 - 构造函数,而不是一个拷贝构造函数,但是这将导致你的类的不同的语义。一招-ctor的需要,使成员作为移动明确通过std::move
:
A(A&& a) : up_(std::move(a.up_)) {}
拥有一整套必要的运营商也导致
A& operator=(const A& a)
{
up_.reset(new int(*a.up_));
return *this,
}
A& operator=(A&& a)
{
up_ = std::move(a.up_);
return *this,
}
如果你想使用你的类中std::vector
,你基本上必须决定矢量是否是一个对象的唯一所有者,在这种情况下,使这个类可移动但不可复制就足够了。如果省去copy-ctor和copy-assignment,编译器会指导你如何使用带移动类型的std :: vector。
丹尼尔·弗雷提及关于复制的解决方案,我就说说如何移动的unique_ptr
#include <memory>
class A
{
public:
A() : a_(new int(33)) {}
A(A &&data) : a_(std::move(data.a_))
{
}
A& operator=(A &&data)
{
a_ = std::move(data.a_);
return *this;
}
private:
std::unique_ptr<int> a_;
};
他们被称为移动构造函数和移动赋值
你可以使用他们喜欢这个
int main()
{
A a;
A b(std::move(a)); //this will call move constructor, transfer the resource of a to b
A c;
a = std::move(c); //this will call move assignment, transfer the resource of c to a
}
你需要用std :: move来包装a和c,因为他们有一个名字 std :: move正在告诉编译器将值转换为 右值引用任何参数都 在技术意义上说,性病::此举是比喻像“的std ::右值”
移动后,的unique_ptr的资源转移到其他的unique_ptr
有记录右值参考的许多主题; this is a pretty easy one to begin with。
编辑:
的移动对象shall remain valid but unspecified state。
C++底漆5,也CH13提供有关“移动”的对象
那么在调用'b'移动构造函数中的std :: move(a)之后会发生什么对象'a'?它完全无效吗? –
如何试试这个帮手创建深层副本,并应对当源的unique_ptr为null,则很能说明问题。
template< class T >
std::unique_ptr<T> copy_unique(const std::unique_ptr<T>& source)
{
return source ? std::make_unique<T>(*source) : nullptr;
}
例如:
class My
{
My(const My& rhs)
: member(copy_unique(rhs.member))
{
}
// ... other methods
private:
std::unique_ptr<SomeType> member;
};
如果源指向从T派生的东西,它会正确复制吗? –
@RomanShapovalov不,可能不会,你会得到切片。在这种情况下,解决方案可能是为您的T类型添加一个虚拟unique_ptr clone()方法,并在从T派生的类型中提供clone()方法的重写。clone方法将创建派生的新实例键入并返回。 –
在C++或boost库中是否没有内置深度复制功能的唯一/范围指针?如果不需要创建我们的自定义拷贝构造函数等是很好的。对于使用这些智能指针的类,当我们需要深度复制行为时,往往是这种情况。就是想。 –
为一体的通常情况下,以具有一个类中的unique_ptr
是能够使用继承(否则一个普通的对象会做为好,见RAII)。对于这种情况,目前还没有适当的答案,直到目前为止。
所以,这里是起点:
struct Base
{
//some stuff
};
struct Derived : public Base
{
//some stuff
};
struct Foo
{
std::unique_ptr<Base> ptr; //points to Derived or some other derived class
};
...而我们的目标是,正如所说,使Foo
可复制的。
为此,需要对包含的指针执行深拷贝以确保派生类被正确复制。
struct Base
{
//some stuff
auto clone() const { return std::unique_ptr<Base>(clone_impl()); }
protected:
virtual Base* clone_impl() const = 0;
};
struct Derived : public Base
{
//some stuff
protected:
virtual Derived* clone_impl() const override { return new Derived(*this); };
};
struct Foo
{
std::unique_ptr<Base> ptr; //points to Derived or some other derived class
//rule of five, but a user-defined dtor is not necessary due to unique_ptr
Foo(Foo const& other) : ptr(other.ptr->clone()) {}
Foo(Foo && other) = default;
Foo& operator=(Foo const& other) { ptr = other.ptr->clone(); return *this; }
Foo& operator=(Foo && other) = default;
};
基本上有两件事情会在这里:
这可以通过添加以下代码实现
首先是增加了复制和移动构造函数,由于
unique_ptr
的复制构造函数被删除,所以在Foo
中隐含地删除了它们。此举构造可以简单地通过= default
加入...这只是让编译器知道,通常的移动构造函数应不被删除(这工作,因为unique_ptr
已经有一个移动构造函数可以在这种情况下使用) 。对于
Foo
的拷贝构造函数,没有类似的机制,因为没有unique_ptr
的拷贝构造函数。所以,我们必须构建一个新的unique_ptr
,用原始指针的副本填充它,并将其用作复制类的成员。在继承的情况下参与,原来指针对象的副本必须谨慎进行。原因是在上面的代码中通过
std::unique_ptr<Base>(*ptr)
进行简单的复制将导致切片,即,只有对象的基本组件被复制,而派生部分丢失。为了避免这种情况,复印,必须通过克隆模式来完成。这个想法是通过一个虚函数
clone_impl()
进行复制,它在基类中返回一个Base*
。然而,在派生类中,它通过协方差扩展返回Derived*
,并且此指针指向派生类的新创建副本。然后基类可以通过基类指针Base*
访问这个新对象,将其包装到unique_ptr
中,并通过从外部调用的实际clone()
函数返回。
- 1. 复制构造函数类
- 2. 字符串类的构造函数和复制构造函数
- 3. 通用集类 - 复制构造函数
- 4. LLVM find_if隐式删除复制构造函数与unique_ptr <>
- 5. 模板类的复制构造函数
- 6. 如何使用复制构造函数
- 7. C++类复制构造函数
- 8. 抽象类,复制构造函数
- 9. 在unique_ptr中删除的构造函数
- 10. 复制构造函数
- 11. 复制构造函数bug
- 12. 复制构造函数
- 13. Cython:复制构造函数
- 14. 复制点构造函数
- 15. doubleLinkedList复制构造函数
- 16. 复制构造函数?
- 17. C++复制构造函数
- 18. Matlab复制构造函数
- 19. 复制构造函数 - C++
- 20. 如何从派生类复制构造函数调用基类复制构造函数?
- 21. 调用unique_ptr子类的继承模板构造函数
- 22. 使用“抽象”超类的复制构造函数
- 23. 如何使用基类的复制构造函数?
- 24. C + +复制构造函数不复制
- 25. 矢量 - push_back使用默认的构造函数不复制构造函数
- 26. 复制构造函数的调用
- 27. 在复制构造函数内调用动态分配的类'复制构造函数?
- 28. boost.variant派生类型:不能使用复制构造函数
- 29. 隐式使用转换构造函数需要复制构造函数
- 30. 复制构造函数去基础构造函数并覆盖复制值
好了,你想要什么的拷贝构造函数呢? –
我读过那个unique_ptr是不可复制的。这让我想知道如何在'std :: vector'中使用具有unique_ptr成员变量的类。 – codefx
我认为复制后,如果我们有2个指向同一位置(对象)的唯一指针的对象,那么这是否有意义?它们应该是唯一的。如果一个带指针的类实现拷贝构造函数,那么该指针应该是共享指针,我相信不是一个唯一的指针。 –