7

I am coming from a C# background to C++. Say I have a method that creates a object in a method on the stack, then I pass it to another classes method which adds it to a memeber vector.

void DoStuff()
{
    SimpleObj so = SimpleObj("Data", 4);
    memobj.Add(so); 
}

//In memobj
void Add(SimpleObj& so)
{
   memVec.push_back(so); //boost::ptr_vector object
}

Here are my questions:

  1. Once the DoStuff methods ends will the so go out of scope and be popped from the stack?
  2. memVec has a pointer to so but it got popped what happens here?
  3. Whats the correct way to pass stack objects to methods that will store them as pointers?

I realise these are probably obvious to a C++ programmer with some expereince.

Mark

3
  • 5
    just as a side note, "SimpleObj so = SimpleObj("Data", 4);" is not very c++ish, use "SimpleObj so("Data", 4);" Commented Sep 21, 2010 at 10:02
  • Thanks, still got some C# hangover.; Commented Sep 21, 2010 at 10:45
  • @milan1612: that unfortunately still remains most portable notation. bunch of c++ compilers fails on the latter, similarly as in the case. Commented Sep 24, 2010 at 22:10

5 Answers 5

9
  1. Yes.
  2. The pointer remains "alive", but points to a no-longer-existent object. This means that the first time you try to dereference such pointer you'll go in undefined behavior (likely your program will crash, or, worse, will continue to run giving "strange" results).
  3. You simply don't do that if you want to keep them after the function returned. That's why heap allocation and containers which store copies of objects are used.

The simplest way to achieve what you are trying to do would be to store a copy of the objects in a normal STL container (e.g. std::vector). If such objects are heavyweight and costly to copy around, you may want to allocate them on the heap store them in a container of adequate smart pointers, e.g. boost::shared_ptr (see the example in @Space_C0wb0y's answer).

Another possibility is to use the boost::ptr_vector in association with boost::ptr_vector_owner; this last class takes care of "owning" the objects stored in the associated ptr_vector, and deleting all the pointers when it goes out of scope. For more information on ptr_vector and ptr_vector_owner, you may want to have a look at this article.

Sign up to request clarification or add additional context in comments.

13 Comments

Thanks, I want to avoid copying objects around, but also avoid having to manage memory on the heap, so I think I'll look at the last two options.
Since you come from C#, I recommend you to have a look also at the other smart pointers provided by boost and learn where each of them is better used. Memory management in C++ isn't as easy as in C#, but using the right smart pointers it becomes almost automatic. BTW, if my answer or another one solved your problem, you may consider marking it as "accepted".
Yeah I am making use of Boost lib, and the smart pointer, just didnt understand them fully, but you have enlightented me, thanks.
In C++0x I'd recommend std::vector<std::unique_ptr<T>>, which is an exception-safe, low-overhead, automatically memory-managing container that probably does everything you want, and better than boost::ptr_vector (which IIRC doesn't work with some STL algorithms).
Yes, the new move semantics makes it possible to write smart pointers that work better in several situations (especially in STL containers). I'd upvote your comment if I had votes left. :)
|
3

To achieve your goal, you should use a shared_ptr:

void DoStuff()
{
    boost::shared_ptr<SimpleObj> so(new SimpleObj("Data", 4));
    memobj.Add(so); 
}

//In memobj
void Add(boost::shared_ptr<SimpleObj> so)
{
   memVec.push_back(so); // std::vector<boost::shared_ptr<SimpleObj> > memVec;
}

4 Comments

Ok that makes sense, so the reference count will be one on the ptr once added to the vector, then it wont be destroyed.
@Mark: Yes. And when the container gets destroyed, the reference count for each shared_ptr in the container will get decreased by one (and the objects will be deleted on the spot if it reaches 0).
I'd recommend unique_ptr instead of shared_ptr if you're using C++0x - there's less overhead. Instead of making copies which increase the reference count, it just gets moved around.
You have to be careful using unique_ptr to avoid accidentally moving out of the container, leaving a NULL pointer behind. Use shared_ptr unless you really know what you're doing.
1

Yes your so object will be popped off the stack once your function leaves scope. You should create a heap object using new and add a pointer to that in your vector.

As said before, the pointer in your vector will point to something undefined once your first function goes out of scope

Comments

1

That code won't compile because inside the Add function you're trying to trying to push a whole object into a vector that expects a pointer to an object.

If instead you were to take the address of that object and push that onto the vector, then it would be dangerous as the original object would soon be popped off the stack and the pointer you stored would be pointing to uninitialised memory.

If you were using a normal vector instead of a pointer vector then the push_back call would be copying the whole object rather than the pointer and thus it would be safe. However, this is not necessarily efficient, and the 'copy everything' approach is probably not intuitive to someone from the C#, Java, or Python worlds.

Comments

0

In order to store a pointer to an object it must be created with new. Otherwise it will disappear when going out of scope.
The easiest solution to your problem as presented here would be to use std::vector instead of boost::ptr_vector, because this way the push_back would copy the object in the vector

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.