2017-10-18 47 views
0

我一直在做一些阅读delete[]new[]what-is-the-rule-of-threedeallocating-objects-stored-in-a-vectordelete-vector-class-member和遇到析构函数呼吁的std ::矢量<Class type>无效的for_each

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

我已经定义的基类

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-> prof是0xCDCDCDCD。

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

+2

如果你真的想要确保以现代C++方式没有内存泄漏,请使用[智能指针](https://stackoverflow.com/questions/106508/what-is-a-smart-pointer-and-when - 应该使用一个)(链接很旧,C++ 11的智能指针被命名为'std :: unique_ptr')。 – spectras

+0

@spectras我完全同意你的看法。我的例子是为了学习正确的内存管理而设计的,但是我在listenbeat中使用'std :: unique_ptr','std :: shared_ptr'和'std :: make_unique()'或者'std :: make_shared()' – Mushy

+0

好吧。那么在你的程序中,'for(auto prof:prof_vec)'在每次迭代时临时拷贝每个教授。这是可能的,因为你没有禁用复制构造函数,并且你的类有一个默认的构造函数和只有微不足道的非静态成员。除了编译器生成的拷贝构造函数只是复制指针,而这个指针必然会出错。如果您不想复制它们,请使用'for(auto&prof:prof_vec)'。并禁用该复制构造函数,您还将捕获push_back()副本。 – spectras

回答

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

完全删除'prof'将是另一个解决方案 –

+0

@ M.M可能,甚至没有注意到它们是同一类型!刚刚看到缺少特殊成员,我内心的警笛响起。 – Barry

2

的构件Professor* prof未在构造Professor()初始化,并且仅在getdata();

当代码进入到外壳2中,如果没有进行初始化任何呼叫getdata(),然后prof保持未初始化。在调试模式下,表示未初始化的值。

相关问题