由于
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提到的,您可以使用move-ctor而不是copy-ctor,但这会导致类的语义不同。move-ctor需要通过
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,
}
如果您想在
在类中具有
那么,起点就在这里:
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
};
。。。目标是,正如所说的,使
为此,需要对包含的指针进行深度复制,以确保正确复制派生类。
这可以通过添加以下代码来实现:
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
~Foo() = default;
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;
};
这里基本上有两件事在进行:
>
添加…这只是为了让编译器知道通常的移动构造函数不会被删除(这是可行的,因为
对于
在涉及继承的情况下,必须认真做好原被指人的复印工作。原因是在上面的代码中通过
为了避免这种情况,必须通过clone-pattern进行复制。其思想是通过一个虚函数
尝试此帮助程序创建深度副本,并在源unique_ptr为空时进行处理。
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;
};