class 向量 unique_ptr 到 class

class with unique_ptr of vector to class

如何将包含 unique_ptr 的 class 实现到包含相同 class 元素的向量以构建某种层次结构。

我之前使用普通指针实现了相同的示例。效果很好。

现在我正在尝试使用 unique_ptr 来适应 c++11。

标有 "works" 注释的行似乎符合我的预期。复制构造中使用的相同类型的语句似乎无法将向量的实际内容复制到新实例中。

我正在使用 Visual Studio 2013.

背景资料:

我已经删除了 class。 iPOD 仅代表 class 中也存在的许多其他成员。 class 用作 HMI 小部件树的单个属性的表示。

#include <string>
#include <memory>
#include <vector>


void func();

struct Attribute;

typedef std::vector<Attribute> AttributeVector;


struct Attribute
{

    int m_iPOD;

    //AttributeVector *m_kAttrVectorPtr; // Old version before unique_ptr did work...
    std::unique_ptr<AttributeVector> m_kAttrVectorPtr; // New version using unique_ptr

    /** Default constructor.  */
    Attribute()
    : m_iPOD(-1), m_kAttrVectorPtr(nullptr)
    {
    }

    /** Constructs an attribute.  */
    Attribute(int iPOD, std::unique_ptr<AttributeVector> kAttrs)
    : m_iPOD(iPOD), m_kAttrVectorPtr(std::move(kAttrs))
    {}

    /** Copy constructor.
     @param kSource Source instance.
     */
    Attribute(const Attribute& kSource)
    : m_iPOD(kSource.m_iPOD)
    {
        if(kSource.m_kAttrVectorPtr)
            m_kAttrVectorPtr = std::unique_ptr<AttributeVector> (new AttributeVector(kSource.m_kAttrVectorPtr));
        else
            m_kAttrVectorPtr = nullptr;
    }

    /** Assignment operator.
     @param kSource Source instance.
     */
    Attribute& operator=(const Attribute& kSource)
    {
        m_iPOD = kSource.m_iPOD;
        if(kSource.m_kAttrVectorPtr)
            m_kAttrVectorPtr = std::unique_ptr<AttributeVector> (new AttributeVector(kSource.m_kAttrVectorPtr));
        else
            m_kAttrVectorPtr = nullptr;
        return *this;
    }

    bool operator==(const Attribute& rkOther) const
    {
        return      m_iPOD == rkOther.m_iPOD; 
       // Todo real compare m_kAttrVectorPtr        == rkOther.m_kAttrVectorPtr;
    }

    bool operator!=(const Attribute& rkOther) const
    {
        return !operator==(rkOther);
    }
};

int main()
{
    AttributeVector kVector;
    Attribute kAttr1;

    kAttr1.m_iPOD = 101;
    kAttr1.m_kAttrVectorPtr = nullptr;

    Attribute kAttr2;

    kAttr2.m_iPOD=102;
    kAttr2.m_kAttrVectorPtr = nullptr;

    kVector.push_back(kAttr1);
    kVector.push_back(kAttr2);

    Attribute kAttr;

    kAttr.m_iPOD=100;
    kAttr.m_kAttrVectorPtr = std::unique_ptr<AttributeVector> (new AttributeVector(kVector)); // Works result= kattr with a vector of 2 attributes

    Attribute kAttrCopy(kAttr);// does not work. Only one entry within m_kAttrVectorPtr after copy instead of the 2 from above
    Attribute kAttrAssign;
    kAttrAssign = kAttr;// does not work. Only one entry within m_kAttrVectorPtr after copy instead of the 2 from above

    return 0;
}

unique_ptr 的想法是在堆上管理一个对象,即一旦指针超出范围就自动 delete 它。 vector 对其内容执行相同的操作,因此在堆上分配 vector 只是浪费资源(时间和内存)。这意味着您之前分配 vector 的设计已经存在缺陷。而不是

struct A {
  vector<A> *pvec;
  A() : pvec(new vector<A>) {}
  ~A() { delete pvec; }
};

(您正尝试使用 unique_ptr 进行改进),只需使用

struct A {
  vector<A> vec;     // requires 24 bytes on 64bit machines
  // auto generated constructor and destructor 
};

或者,如果一开始就知道 vector 中包含的对象数量,您可以使用 unique_ptr:

struct A {
  unique_ptr<A[]> vec;   // requires 8 bytes on 64bit machines
  A(size_t n)
  : vec(new A[n]) {}
};

new AttributeVector(kSource.m_kAttrVectorPtr) 替换为 new AttributeVector(*kSource.m_kAttrVectorPtr)

您不能使用任何指针构造向量,而只能使用值本身。 (*)