Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to get stl map to construct/destruct inserted object only once

Tags:

c++

stl

I have found a very prejudicial fact about stl maps. For some reason I cant get objects being inserted in the map to get constructed/destructed only once.

Example:

struct MyObject{
    MyObject(){
        cout << "constructor" << endl;
    }
    ~MyObject(){
        cout << "destructor" << endl;
    }
};
int main() {
    std::map<int, MyObject> myObjectsMap;
    myObjectsMap[0] = MyObject();
    return 0;
}

returns:

constructor
destructor
destructor
constructor
destructor

If I do:

typedef std::pair<int, MyObject> MyObjectPair;
myObjectsMap.insert( MyObjectPair(0,MyObject()));

returns:

constructor
destructor
destructor
destructor

I'm inserting Objects responsible for their own memory allocation, so when destructed they'll clean themselves up, being destructed several times is causing me some trouble.

like image 503
Alberto Toglia Avatar asked Jun 06 '10 16:06

Alberto Toglia


2 Answers

I suggest you add a copy constructor - that's what is being used for the 'missing' constructions I think.

Code:

#include <iostream>
#include <map>

using namespace std;

struct MyObject{
    MyObject(){
        cout << "no-arg constructor" << endl;
    }
    MyObject(const MyObject&) {
    cout << "const copy constructor" << endl;
    }
    ~MyObject(){
        cout << "destructor" << endl;
    }
};
int main() {
    std::map<int, MyObject> myObjectsMap;
    myObjectsMap[0] = MyObject();
    return 0;
}

Output:

no-arg constructor
const copy constructor
const copy constructor
destructor
destructor
no-arg constructor
destructor
destructor
like image 120
Douglas Leeder Avatar answered Sep 18 '22 01:09

Douglas Leeder


std::map is allowed to make as many copies of your objects as it wishes. This is implementation defined and you have no control over this. The "missing" constructions you notice, by the way, may be for calling the copy-constructor, which you didn't define.

What you can do, however is use a flyweight so constructing an object in fact fetches a existing object from a pool of pre-existing objects, and destructing an object does nothing. The pool never frees its objects, but it always maintains a handle over all of them. This way, your memory usage is large from start to stop, but it doesn't change much throughout the life of the program.

like image 41
wilhelmtell Avatar answered Sep 22 '22 01:09

wilhelmtell