C++ 在堆上分配元素的向量-我需要规则5吗?

C++ 在堆上分配元素的向量-我需要规则5吗?,c++,destructor,rule-of-five,C++,Destructor,Rule Of Five,如果我有这样一个班级: class MyClass { public: void set_my_vector() { for (int ind = 0; ind < 3; ++ind) { my_vector.push_back(new MyStruct(i, i*2)); } } private: struct MyStruct { int num_a; int num_b;

如果我有这样一个班级:

class MyClass {
public:
    void set_my_vector() {
        for (int ind = 0; ind < 3; ++ind) {
            my_vector.push_back(new MyStruct(i, i*2));
        }
    }
private:
    struct MyStruct {
        int num_a;
        int num_b;
        MyStruct(int i, int j) : num_a(i), num_b(j) {}
    };
    std::vector<MyStruct*> my_vector;
};
我是否需要编写五个函数的规则,或者std::vector将负责深度复制和删除堆上分配的元素

编辑: 下面的代码使用默认的复制构造函数,因此我假设在我将我的\u class1对象复制到我的\u class2对象之后,我的\u class1.my\u向量和我的\u class2.my\u向量的元素将是相同的,因为MyStruct指针被复制,而不是数据本身。但是,输出结果表明它们并不相同。您可以在此处运行代码:


编辑2:我知道智能指针。我特别感兴趣的是如果我使用原始指针会发生什么。

您需要实现复制构造函数、复制赋值和析构函数

另外,考虑将向量声明从

中更改
std::vector<MyStruct*> my_vector;


因此,它实际上正确地拥有堆分配的对象。执行此更改将帮助您不编写析构函数。

您需要实现复制构造函数、复制赋值和析构函数

另外,考虑将向量声明从

中更改
std::vector<MyStruct*> my_vector;

因此,它实际上正确地拥有堆分配的对象。执行此更改将帮助您不编写析构函数。

不,std::vector不负责对指针存储的对象进行深度复制。您几乎没有解决此问题的可能性:

按值存储MyStruct。 存储标准::唯一\u ptr。 存储标准::共享\u ptr。 请注意,由于MyStruct只包含基元类型的字段,所以不需要复制构造函数、赋值运算符和析构函数,否则必须实现它们,编译器将自动生成的默认实现就足够了。

否,vector不负责指针存储的对象的深度复制。您几乎没有解决此问题的可能性:

按值存储MyStruct。 存储标准::唯一\u ptr。 存储标准::共享\u ptr。
注意,因为MyStruct只包含原语类型的字段,所以不需要复制构造函数、赋值运算符和析构函数,否则必须实现它们,编译器将自动生成的默认实现就足够了。

您能根据我对原始帖子的编辑添加更多详细信息吗?如果我使用默认的复制构造函数,会发生什么?你能根据我对原始帖子的编辑添加更多细节吗?如果我使用默认的复制构造函数,会发生什么情况?正如您猜测的,并且您最近的编辑已经确认,向量会为您复制其元素。如果这些元素恰好是指向其他对象的指针,那么就只能靠自己了。地址被复制,因为它们是元素的值,而不是指向对象的值。你是否需要三五法则的保护取决于那些指向物体的人。在这种情况下,您可能至少需要三条规则,但如果只复制指针,那么在MyClass之后my_class2=my_class1;和我的2类。填充我的向量12,13;,我想我的大学是一年级。我的_向量也有元素12,13。但它有42、43个元素,为什么?你把指针和它们指向的对象混为一谈了。指针是一个恰好保存另一个对象地址的对象。这里的指针已被复制,最初两个副本都指向同一个位置。您可以将其中一个指针指向其他地方,并有两个指向不同对象的指针,但在本例中,my_class2的向量被清除-不再有任何指针,并充满指向全新对象的全新指针。这两门课之间已经没有任何联系了。建议:坐下来,画一些谁在指着什么,什么时候指着的图片,帮助自己想象正在发生的事情。哦,我明白了,这是有道理的。谢谢,@user4581301。正如您猜测的,并且您最近的编辑已经确认,一个向量为您复制了它的元素。如果这些元素恰好是指向其他对象的指针,那么就只能靠自己了。地址被复制,因为它们是元素的值,而不是指向对象的值。你是否需要三五法则的保护取决于那些指向物体的人。在这种情况下,您可能至少需要三条规则,但如果只复制指针,那么在MyClass之后my_class2=my_class1;和我的2类。填充我的向量12,13;,我想我的大学是一年级。我的_向量也有元素12,13。但它有42、43个元素,为什么?你把指针和它们指向的对象混为一谈了。指针是一个恰好保存另一个对象地址的对象。这里的指针已被复制,最初两个副本都指向同一个位置。您可以将其中一个指针指向其他地方,并将两个指针指向不同的对象,但在本例中,my_class2的向量被清除-不再有任何指针,并充满指向completel的全新指针
创建新对象。这两门课之间已经没有任何联系了。建议:坐下来,画一些谁在指着什么,什么时候指着的图片,帮助自己想象正在发生的事情。哦,我明白了,这是有道理的。谢谢,@user4581301。如果std::vector不能处理深度复制,那么为什么编译器自动生成的默认实现就足够好了?我假设默认实现将对vector的元素进行浅层复制,不是吗?复制构造函数、赋值和析构函数仅在类中维护一些非平凡状态时才需要,比如,若你们有指向某个对象的指针,那个么当你们创建新对象或赋值时,你们必须复制那个对象。基本数字类型(如int、double等)的成员变量可以逐位复制,这是编译器默认的做法,因此已经足够好了。如果std::vector不负责深度复制,那么为什么编译器自动生成的默认实现就足够好了?我假设默认实现将对vector的元素进行浅层复制,不是吗?复制构造函数、赋值和析构函数仅在类中维护一些非平凡状态时才需要,比如,若你们有指向某个对象的指针,那个么当你们创建新对象或赋值时,你们必须复制那个对象。基本数字类型的成员变量(如int、double等)可以逐位复制,这是编译器默认的做法,所以已经足够好了。
std::vector<std::unique_ptr<MyStruct>> my_vector;