简体   繁体   中英

C++ Storing objects (with pointer to another object) in vector

I'd like to store MyClass in vector. MyClass has pointer to InnerClass and ind destructor of MyClass I'd like to deallocate memory for previously allocated InnerClass object.

Here's my code:

#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;
}

And here's output:

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 ***

The question is: why do I get this error?

You have not implemented the copy constructor correctly and also you have not provided an assignement operator for MyClass. Now my is a local variable for the cycle so it's destructor is called once the cycle iteration finishes. However a MyClass with pointer to the already freed object is pushed in the vector cont . Later on the destructor of this instance will also be called(when the destructor of the vector is called) and will try to free the memory once more.

Correct way to implement assignment operator and copy constructor when dealing with dynamic memory like you do is to allocate a new object and copy the contents.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM