2013-05-27 2 views
0

Я хотел бы хранить MyClass в векторе. MyClass имеет указатель на InnerClass и ind destructor MyClass, я хотел бы освободить память для ранее выделенного объекта InnerClass.C++ Сохранение объектов (с указателем на другой объект) в векторе

Вот мой код:

#include <iostream> 
#include <algorithm> 
#include <vector> 
#include <map> 

#define PB push_back 
#define MP make_pair 

using namespace std; 

int cnt; 
map<int, int> m; 

void mark(int id) { 
    if(m.find(id) != m.end()) 
     cout << "ERROR! " << id << " was marked before" << endl; 
    m[id] = 1; 
} 

void unmark(int id) { 
    if(m[id] != 1) 
     cout << "ERROR! " << id << " was not marked before" << endl; 
    m[id] = 0; 
} 

void look() { 
    cout << endl; 
    for(int i=0;i<cnt;++i) { 
     cout << i << ": " << m[i] << endl; 
    } 
    cout << endl; 
} 

class InnerClass { 
    public: 
    InnerClass(int _id) { 
     cout << "InnerClass::InnerClass(int) called (#" << _id << ")" << endl; 
     id = _id; 
    } 
    InnerClass(const InnerClass& org) { 
     cout << "InnerClass::InnerClass(const InnerClass&) called (#" << org.id << ")" << endl; 
     id = org.id; 
    } 
    int getID() { 
     return id; 
    } 
    private: 
    int id; 
}; 

class MyClass { 
    public: 
    MyClass(InnerClass* _inner) { 
     id = cnt++; 
     mark(id); 
     cout << "MyClass::MyClass(InnerClass*) called (#" << id << ")" << endl; 
     inner = _inner; 
    } 
    MyClass(const MyClass& org) { 
     id = cnt++; 
     mark(id); 
     cout << "MyClass::MyClass(const MyClass&) called (#" << id << " <- #" << org.id << ")" << endl; 
     inner = new InnerClass(org.inner->getID()); 
    } 
    ~MyClass() { 
     unmark(id); 
     cout << "MyClass::~MyClass() called (#" << id << ")" << endl; 
     delete inner; 
    } 
    private: 
    InnerClass* inner; 
    int id; 
}; 

bool cmp(const pair<double, MyClass > &p, const pair<double, MyClass > &r) { 
    return p.first < r.first; 
} 

int main() { 
    vector<pair<double, MyClass> > cont; 
    int n = 3; 
    for(int i=0;i<n;++i) { 
     InnerClass* inner = new InnerClass(i); 
     MyClass my(inner); 
     cont.PB(MP((double)i, my)); 
    } 
    look(); 
    cout << "Sorting" << endl; 
    sort(cont.begin(), cont.end(), cmp); 
    return 0; 
} 

И вот результат:

InnerClass::InnerClass(int) called (#0) 
MyClass::MyClass(InnerClass*) called (#0) 
MyClass::MyClass(const MyClass&) called (#1 <- #0) 
InnerClass::InnerClass(int) called (#0) 
MyClass::MyClass(const MyClass&) called (#2 <- #1) 
InnerClass::InnerClass(int) called (#0) 
MyClass::MyClass(const MyClass&) called (#3 <- #2) 
InnerClass::InnerClass(int) called (#0) 
MyClass::~MyClass() called (#2) 
MyClass::~MyClass() called (#1) 
MyClass::~MyClass() called (#0) 
InnerClass::InnerClass(int) called (#1) 
MyClass::MyClass(InnerClass*) called (#4) 
MyClass::MyClass(const MyClass&) called (#5 <- #4) 
InnerClass::InnerClass(int) called (#1) 
MyClass::MyClass(const MyClass&) called (#6 <- #5) 
InnerClass::InnerClass(int) called (#1) 
MyClass::MyClass(const MyClass&) called (#7 <- #6) 
InnerClass::InnerClass(int) called (#1) 
MyClass::MyClass(const MyClass&) called (#8 <- #3) 
InnerClass::InnerClass(int) called (#0) 
MyClass::~MyClass() called (#3) 
MyClass::~MyClass() called (#6) 
MyClass::~MyClass() called (#5) 
MyClass::~MyClass() called (#4) 
InnerClass::InnerClass(int) called (#2) 
MyClass::MyClass(InnerClass*) called (#9) 
MyClass::MyClass(const MyClass&) called (#10 <- #9) 
InnerClass::InnerClass(int) called (#2) 
MyClass::MyClass(const MyClass&) called (#11 <- #10) 
InnerClass::InnerClass(int) called (#2) 
MyClass::MyClass(const MyClass&) called (#12 <- #11) 
InnerClass::InnerClass(int) called (#2) 
MyClass::MyClass(const MyClass&) called (#13 <- #8) 
InnerClass::InnerClass(int) called (#0) 
MyClass::MyClass(const MyClass&) called (#14 <- #7) 
InnerClass::InnerClass(int) called (#1) 
MyClass::~MyClass() called (#8) 
MyClass::~MyClass() called (#7) 
MyClass::~MyClass() called (#11) 
MyClass::~MyClass() called (#10) 
MyClass::~MyClass() called (#9) 

0: 0 
1: 0 
2: 0 
3: 0 
4: 0 
5: 0 
6: 0 
7: 0 
8: 0 
9: 0 
10: 0 
11: 0 
12: 1 
13: 1 
14: 1 

Sorting 
MyClass::MyClass(const MyClass&) called (#15 <- #14) 
InnerClass::InnerClass(int) called (#1) 
MyClass::~MyClass() called (#15) 
MyClass::MyClass(const MyClass&) called (#16 <- #12) 
InnerClass::InnerClass(int) called (#2) 
MyClass::~MyClass() called (#16) 
MyClass::~MyClass() called (#13) 
ERROR! 15 was not marked before 
MyClass::~MyClass() called (#15) 
ERROR! 16 was not marked before 
MyClass::~MyClass() called (#16) 
*** glibc detected *** ./vector-class: double free or corruption (fasttop): 0x000000000194c6b0 *** 

Возникает вопрос: почему я получаю эту ошибку?

+0

Вы не следуете Правилу Трех. Вы должны просто использовать интеллектуальный указатель. – chris

+0

@chris лучше: они должны просто не использовать ничего. 'InnerClass inner' будет работать отлично. –

+0

Не используйте 'id = _id;'. Вместо этого используйте инициализаторы-члены (см. Http://stackoverflow.com/q/1711990/46642). Если именно так ваша книга научила вас писать конструкторы, вы, вероятно, не должны доверять ей, потому что в конечном итоге вы изучите очень раздражающий, очень ограниченный и очень хрупкий способ написания C++. У нас есть список хороших книг здесь: http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list. –

ответ

0

Вы не внедрили конструктор копирования правильно, а также вы не предоставили оператора присвоения для MyClass. Теперь my является локальной переменной для цикла, так что деструктор вызывается после завершения итерации цикла. Однако MyClass с указателем на уже освобожденный объект помещается в вектор cont. Позже будет вызываться деструктор этого экземпляра (когда вызывается деструктор вектора) и попытается освободить память еще раз.

Правильный способ реализации оператора присваивания и конструктора копирования при работе с динамической памятью, как и вы, состоит в том, чтобы выделить новый объект и скопировать его содержимое.

Смежные вопросы