1

如果我的班级成员是这样的:

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 会负责深度复制和删除堆上分配的元素?

编辑:以下代码使用默认的复制构造函数,所以我假设在我将 my_class1 对象复制到 my_class2 对象后,my_class1.my_vector 和 my_class2.my_vector 的元素将是相同的,因为复制了 MyStruct 指针,而不是数据本身. 但是,输出显示它们并不相同。您可以在此处运行代码:https ://onlinegdb.com/S1pK9YE4v

#include <iostream>
#include <vector>

class MyClass {
public:    
    void fill_my_vector(int i, int j) {
        my_vector.clear();
        for (int ind = 0; ind < 3; ++ind) {
            my_vector.push_back(new MyStruct(i, j));
        }
    }

    void print () {
        for (int ind = 0; ind < 3; ++ind) {
            std::cout << my_vector[ind]->int1 << ", " << my_vector[ind]->int2 << std::endl;
        }
        std::cout << std::endl;
    }
private:
    struct MyStruct {
        MyStruct (int i, int j) :
        int1(i), int2(j)
        {}
    
        int int1;
        int int2;
    };

    std::vector<MyStruct*> my_vector;
};

int main()
{
    MyClass my_class1;
    my_class1.fill_my_vector(42, 43);

    std::cout << "my_class1: " << std::endl;
    my_class1.print();

    MyClass my_class2 = my_class1;
    my_class2.fill_my_vector(12, 13);

    std::cout << "my_class2: " << std::endl;
    my_class2.print();

    std::cout << "my_class1: " << std::endl;
    my_class1.print();

}

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

4

2 回答 2

2

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

此外,考虑将您的向量声明从

std::vector<MyStruct*> my_vector;

std::vector<std::unique_ptr<MyStruct>> my_vector;

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

于 2020-09-08T04:32:49.477 回答
1

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

  • 按价值存储MyStruct
  • 存储std::unique_ptr<MyStruct>
  • 存储std::shared_ptr<MyStruct>

请注意,由于MyStruct只包含原始类型的字段,因此不需要复制构造函数、赋值运算符和析构函数,否则您必须实现它们,编译器将自动生成的默认实现就足够了。

于 2020-09-08T05:25:50.523 回答