析构函数调用std :: vector <class type =“”>使for_each无效

时间:2017-10-18 00:12:53

标签: c++ c++11 memory-management memory-leaks delete-operator

我一直在阅读delete[]new[]what-is-the-rule-of-threedeallocating-objects-stored-in-a-vectordelete-vector-class-member并遇到

  

抛出异常:读取访问冲突。

我已经定义了一个基类

class Person
{
private:
    std::string name;
    int age;
    static int cur_id;
public:
    Person() {}
    Person(std::string new_name, int new_age) : name(new_name), age(new_age) { cur_id += 1; }
    virtual ~Person() {}
    void setname(std::string name) { this->name = name; }
    std::string getname() { return name; }
    int getage() { return age; }
    void setage(int age) { this->age = age; }
    int get_id() { return cur_id; }

    virtual void getdata(void) = 0;
    virtual void putdata(void) = 0;
};

派生类

class Professor : private Person
{
private:
    int publications;
    Professor* prof;
public:
    Professor() {}
    Professor(std::string new_name, int new_age, int new_pubs) : Person(new_name, new_age) { this->publications = new_pubs; }
    ~Professor() override { delete prof; }
    void getdata() override 
    {
        std::vector<std::string> prof_input = get_input();
        std::cout << prof_input[0] << "\n";
        std::cout << std::stoi(prof_input[1]) << "\n";
        std::cout << std::stoi(prof_input[2]) << "\n";
        prof = new Professor(prof_input[0], std::stoi(prof_input[1]), std::stoi(prof_input[2]));
    }
    void putdata() override 
    {
        std::cout << prof->getname() << " " << prof->getage() << " " << prof->publications << " " << prof->get_id();
    }
};

并定义了主要

int main()
{
    int size; 

    std::cin >> size;

    std::cin.ignore();

    Professor* prof = new Professor();

    std::vector<Professor> prof_vec;

    for (int i = 0; i < size; i++)
    {
        int which;
        std::cin >> which;
        std::cin.ignore();

        switch (which)
        {
        case 1: 
        {
            prof->getdata();
            prof_vec.push_back(*prof);
        }
        break;
        case 2:
        {
            // something else
        }
        break;
        }
    }

    for (auto prof : prof_vec)
    {
        prof.putdata();
    }  <<< ------------------- Things so south here

    delete prof;

    fgetc(stdin);

    return 0;
}

我想到的是(假设向量中只有一个元素),一旦调用putdata()退出块,析构函数调用delete prof就会出现

  

this-&gt; prof是0xCDCDCDCD。

我正在尝试删除不存在的对象。如果我想确保delete正确,即使有这样一个简单的例子,我应该做些什么来确保没有内存泄漏?

2 个答案:

答案 0 :(得分:4)

您违反了rule of 3/5/0

class Professor : private Person
{
private:
    Professor* prof;
public:
    // ...
    ~Professor() override { delete prof; }
};

如果您提供其中一个特殊成员函数,则应提供所有特殊成员函数。在这种情况下,您的复制构造函数只是成员复制Professor*,现在您有两个不同的对象试图删除相同的指针。

首选规则0:

class Professor : private Person
{
private:
    std::unique_ptr<Professor> prof;
public:
    // ...
    ~Professor() = default;
};

答案 1 :(得分:2)

成员Professor* prof未在构造函数Professor()中初始化,仅在getdata();初始化

当代码转到案例2时,如果没有对getdata()的任何调用,则prof将保持未初始化状态。

0xCDCDCDCD表示调试模式中未初始化的值。