How to get stl-map to create / destroy an inserted object only once

I found a very biased fact about stl cards. For some reason, I can’t get the objects inserted in the map to get / destroy 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 this:

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

returns:

 constructor destructor destructor destructor 

I insert the objects responsible for their own memory allocation, so when they are destroyed, they will be cleaned, being somewhat destroyed, it causes me certain problems.

+6
c ++ stl
source share
5 answers

I suggest you add a copy constructor - this is what is used for the “missing” constructs that I think.

the 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 
+6
source share

std::map allowed to make as many copies of your objects as you wish. This implementation is defined, and you do not control it. The “missing” constructs that you notice, by the way, may be for calling a copy constructor that you did not define.

However, you can use flies, so building an object actually extracts an existing object from the pool of existing objects, and destroying the object does nothing. The pool never frees its objects, but always maintains a handle to all of them. Thus, the use of your memory is great from start to stop, but it does not greatly change life throughout the program.

+4
source share

To be in a standard container, your objects must be copyable and assignable. If your objects do not match this, you may have problems.

However, if (as your code example points out) you only need the default built object inserted on the map, you can simply use the [] operator for its side effect:

 // Insert default constructed MyObject at key 0 myObjectsMap[0]; 

Edit

I am not entirely clear from your question, but if you are unclear about the number of built objects and believe that there is a constructor / destructor mismatch, then note that the compiler will provide a copy constructor that is not registered in std::cout , since you are not providing the declared by user.

+2
source share

When you say myObjectsMap [0], you call the default constructor for MyObject. This is because there is nothing in [0], and you just turned to it. This is in the manual .

When you hit MyObject (); you create a temporary instance of MyObject using the default constructor.

Since you allowed the compiler to define your copy constructor, you will see more destructors than constructor messages. (Unlike a house building, there can only be one destructor, but many constructors.) If you do not need to copy this object, then you probably want to declare a private copy constructor and copy operator.

You call the default constructor and copy constructor twice each using this code:

 myObjectsMap[0] = MyObject(); 

When you do this:

 myObjectsMap.insert( MyObjectPair(0,MyObject())); 

you call the default constructor once and the copy constructor 3 times.

You should probably use pointers as map values ​​instead of the objects themselves, in particular, I suggest looking at shared_ptr.

 note: tests were done using GCC 3.4.5 on a Windows NT 5.1 machine. 
+2
source share

For the map path and other containers to work, you cannot get around it. This is why std::auto_ptr cannot be used in a collection, for example.

+1
source share

All Articles