3

I'm new to C++ so still learning about pointers and getting used to using them.

I have declared an object map in order to store objects that the user might access later on using the tag key.

map<string,MyObject*> myMap;

The objects I'm adding to myMap are created in a function called by my main

void myFunction(){
    ...
    MyObject obj1();
    MyObject* objPtr;
    objPtr = &obj1;
    myMap.insert(pair<string,MyObject*>("xxxx", objPtr));
    ...
    } 

When I execute this function the object pointer is perfectly inserted to myMap, but after the function execution I lose the reference to obj1 I guess because the pointer and the object were created locally inside the function, so I still have an element "xxx" in the map but with what I think is an empty reference after.

How can I keep the object and the reference globally? I wanted to create this object in the function since it has some variable parameters that needs to get from a user obj1(m,n). Thanks for any help.

JLA
  • 329
  • 1
  • 6
  • 12
  • 2
    Any reason why you cannot store objects in the map? That would greatly simplify things. – juanchopanza Oct 27 '13 at 21:06
  • Why don't you use `objPtr = new MyObject();` instead of `MyObject obj1(); objPtr = &obj1;` ? This creates the object on the heap where it outlives the scope of the function. However, you need to delete the objects after you finished using the objects and the map. In your example the object is created on the stack and deleted after the function finishes. – MKroehnert Oct 27 '13 at 21:08
  • You probably want to learn about the `new` keyword. – n. m. could be an AI Oct 27 '13 at 21:08
  • You probably meant `MyObject obj1;`? Because your line of code `MyObject obj1();` will define [a function pointer variable](http://ideone.com/LHluQe). – leemes Oct 27 '13 at 21:14

3 Answers3

5

The code line

MyObject obj1;

defines a local variable which holds an instance of MyObject. Once the context of this variable is about to be left, the object will be destructed. Destruction of objects doesn't mean that pointers which point to them will be notified in any way (they are not set to 0 for example), accessing them is invalid.

You have basically the following options:

  • Create the object on the heap instead of locally. This is done using the new keyword. But then you have to delete the object at some point.

    MyObject *obj1 = new MyObject(arguments...);
    
  • Since this is often difficult to manage, smart pointers where invented. For example, since C++11, the shared_ptr was added (but it's also available in some compilers with the pre-release version C++0x). This type of smart pointer will automatically delete the object for you when the last reference will be destroyed.

    map<string,std::shared_ptr<MyObject>> myMap; // Note that I changed the type
    
    std::shared_ptr<MyObject> obj1 = std::make_shared<MyObject>(arguments...);
    myMap.insert(std::make_pair("xxxx", obj1));
    

    By the way, I used std::make_pair which will automatically deduce the template types for you.

  • Store values in the map. Don't use pointers at all. This is an option if your type can be copied (some types can't) as well as if some of your design decisions doesn't forbid you to do so. But in most cases it will be a good idea to store the values in the map. Please use references when fetching an element from the map which you want to modify:

    MyObject &obj = myMap["xxxx"]; // looking up the key
    obj.doSomeAction();            // modify it; no need to re-insert
    

    References behave similar to pointers (i.e. they only "point at" some instance), but there are some differences. For example, references always point to the same instance over their lifetime (you can't reassign references). Also, their syntax is equal to values, i.e. no -> required.

Personally, I'd prefer the third option if you don't need to put pointers to the same object at multiple places in your program. If this was the case, we speak of "shared" objects which is exactly the case where you want to use "shared" pointers. The first option is very low-level and should be considered "obsolete".

Community
  • 1
  • 1
leemes
  • 44,967
  • 21
  • 135
  • 183
  • +1 for using `shared_ptr` but could you point out that this is only available in the latest standard? – MKroehnert Oct 27 '13 at 21:13
  • Thank you so much leemes, just storing the object instead of the pointers fixed all the problems... and your explanation was very helpful – JLA Oct 27 '13 at 21:43
3

Unless you have a strong reason to do otherwise, it might be simpler to store objects in the map:

map<string, MyObject> myMap;

Then:

void myFunction(){
  ...
  myMap.insert(std::make_pair("xxxx", MyObject()));
  ...
} 
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
2

You can instantiate your object dynamically.

MyObject* objPtr = new MyObject;

But do not forget to delete this instance when you won't use it anymore with

delete objPtr;
Masadow
  • 762
  • 5
  • 15
  • 1
    You have to be careful with deleting just the `objPtr` since it invalidates the pointer which is stored in the map. – MKroehnert Oct 27 '13 at 21:11