类的C ++赋值运算符包含唯一的指针成员变量

时间:2019-04-18 10:15:03

标签: c++ unique-ptr assignment-operator

我知道,如果我有一个带有智能唯一指针的类,则无法将该类分配给另一个实例,因为不能复制唯一指针。我知道我可以使唯一指针成为共享指针,这样就可以解决问题。但是,如果我不想共享指针的所有权怎么办?是否可以创建一个赋值运算符来移动唯一指针并复制其他变量?

我了解到您可以使用std::move来转让所有权。

#include <iostream>
#include <memory> 

struct GraphStructure { };

class test {

        int a;
        std::vector<int> vector;
        std::unique_ptr<GraphStructure> Graph_; 
 };

 int main () {

     test t1;
     auto t2 = t1;
 }

2 个答案:

答案 0 :(得分:5)

test的默认 copy 构造函数被删除,因为成员(graph_)无法复制(如果您仍然可以通过任何有意义的方式进行复制,例如通过创建图成员的 deep 副本,您必须在自己的副本构造函数上实现)。相反,默认的 move 构造函数仍然存在(std::unique_ptr是可移动的)。因此,您可以执行以下操作:

test t1;
auto t2 = std::move(t1);

不过请注意,t1然后不再不再持有任何对象(您移动了该对象,因此将其内容移动到了另一个对象一个),先前由t2持有的对象将被销毁。如果这是有意义的状态,则由您决定...

侧面说明:我写的有关复制和移动构造函数的内容也适用于复制和移动分配...

答案 1 :(得分:3)

以简单的方式修复

如果GraphStructure是没有任何虚拟成员函数的类或结构,则很容易做到。我们可以编写一个函数来复制unique_ptr内部的数据以创建新的GraphStructure

std::unique_ptr<GraphStructure> duplicate(std::unique_ptr<GraphStructure> const& ptr)
{
    return std::make_unique<GraphStructure>(*ptr);
}

有了duplicate之后,我们可以使用此类编写用于测试的副本构造函数:

class test {
    std::unique_ptr<GraphStructure> ptr;
    std::vector<int> values;
   public:
    // this can be defaulted
    test() = default;
    // we use duplicate to create a copy constructor
    test(const test& source) 
      : ptr(duplicate(source.ptr)))
      , values(source.values)
    {}
    // we can use the default move constructor
    test(test&&) = default;

    test& operator=(test const& source) {
        ptr = duplicate(source.ptr);
        values = source.values; 
        return *this;
    }
    // we can use the default move assignment operator 
    test& operator=(test&&) = default;
};

如果GraphStructure具有虚拟方法怎么办?

在这种情况下,向GraphStructure添加一个虚拟clone方法,该方法将返回一个新的std::unique_ptr<GraphStructure>

class GraphStructure {
   public:
    // override this method in child classes
    virtual std::unique_ptr<GraphStructure> clone() {
        return std::make_unique<GraphStructure>(*this);
    }
    virtual ~GraphStructure() {}
};

然后,使用.clone()代替duplicate