Can I keep vector data even after out of scope - c++

I come from a C background. I used to allocate memory/array, for example, sending it to somewhere else, and the pointer stayed there, even after, the scope where it was allocated was destroyed.
Now, if I do the same with vectors : initialize, pass it by reference, and then keep that reference saved somewhere. After the initial method, that actually created the vector, goes out of scope, would it be destroyed ? Or as the pointer to it is still saved, it will be kept.

std::vector frees the memory it holds when it is destroyed. Holding a reference to an object that gets destroyed is very bad. Accessing it is UB. General rule: Do not store references, only use them where you can be sure that the object exists for the entire scope, e.g. as parameter of a function.
If you want to keep a copy of the data, simply copy the std::vector. No reference needed.
If you want to be able to access the data from different locations, and have it live as long as at least one location still has a reference/pointer to it, don't use std::vector, use std::shared_ptr.
If you want to combine the benefits of std::vector with the benefits of shared memory that lives until the last place lets go of it, combine them: std::shared_ptr<std::vector<...>>.
If you want to have the std::vector live in one place for a bit, and then live in another place but not in the first place anymore, use move semantics:
std::vector<int> foo = {1, 2, 3};
std::vector<int> bar = std::move(foo); // bar now holds the data that foo held, foo is empty, no copy was performed

A pointer to an array on the stack will not keep the array alive, I suppose thats the same in C. Now a vector is not an array. It is a wrapper around a heap allocated array which frees the memory of the array when it goes out of scope.
... because a pointer to it is still saved it will still be kept?
No! A pointer or reference to a std::vector will not keep the vector alive. The canonical wrong example is:
std::vector<T>& foo() {
std::vector<T> x;
return x;
} // baaam !
The reference returned from the function is dangling. YOu cannot do anything with it. The correct way would be to return by value and rely on return value optimization:
std::vector<T> foo() {
std::vector<T> x;
return x;
}
If you do:
auto y = foo();
No copying is involved, thanks to NRVO.
PS: Compilers should warn you about returning a reference to a local variable.

No if I do the same with vectors, I initialize a vector, pass it by reference, then keep the reference saved somewhere. After the initial method that actually created the vector goes out of scope, would it be destoryed?
Yes.
or because a pointer to it is still saved it will still be kept?
No.
You can have dangling pointers in C++ just like you can in C. It's exactly the same.
This is also often the case for references (though in some cases the lifetime of the object is extended for a little bit).
It is true that the vector's data is internally managed by the vector, but that's by-the-by since you're asking about the vector itself. Forget the vector and ask the same question about an int, then you'll realise the answer is just as you'd expect it to be in C.

The existing answers are good, will add here:
block A
{
vector<int> my_vec(10, 0);
//...something...
}
block B
The my_vec vector will go out of scope and be destroyed at the closing bracket. Now that's stl (Standard Template Library) vectors.
You can also use C-style arrays (but with different syntax). For very large arrays, I have found the allocation time with a dynamically-allocated array to be faster than STL vectors.
//static, goes out of scope and memory handled at the end of code block
int arr0[10];
//dynamic, not destroyed unless delete called.
int* arr1 = new int[10];
//...work with arr1...
delete [] arr1;
Just like in C, you need to take care of de-allocating any memory you create using new.

Related

Is it possible to return an a reference to the data in an std::vector, and preserve that reference after the vector goes out of scope?

I am used to programming in C, and in that language I would just return a pointer to the data, and then the caller would be responsible for freeing the data, however, from what I've read, the vector's destructor will be called as soon as it goes out of scope, causing it's data to be de-allocated.
Once the reference is returned, the size of the contents will not change, so if I could just have a pointer to the data that I could manually delete afterwards that would be ideal. What I really do not want to do is copy all of the data into a new container, since this vector is going to grow to be very large.
Any help would be appreciated. Every solution I have seen so far involves either copying by value and relying on the compiler to optimize it, or using additional classes to wrap the vector.
Edit: To be clear, the only part of the vector which I want to keep is a pointer to its data (I.E. the pointer you get using the vector.data() method), I don't need to keep any other information about the original vector.
Good (safe and fast) solution for the use case that you describe: Don't return a reference, return the vector to the outside of the scope instead.
Is it possible to return an a reference to the data in an std::vector, and preserve that reference after the vector goes out of scope?
Yes... if you use static storage. The lifetime of objects with static storage duration extends until the end of the program. Therefore they stay alive when they go out of scope. Note that static storage is global state, which is often problematic. Avoid if you can and use with care.
With automatic storage: No.
I would just return a pointer to the data, and then the caller would be responsible for freeing the data
This is a problematic approach. How does the caller know that they are responsible for freeing the data? How does the caller know how to free the data? How does the caller know when they can free the data (in case there are other users of the data)? This all relies on the caller to read the documentation, understand it, and not make a mistake. This is a source of many memory leaks, accesses through invalid pointers and double free crashes.
std::vector solves those problems (to some degree; there are no interfaces in C or C++ that cannot be misused if one tries hard enough) by keeping the lifetime tied to the container object.
If I could just have a pointer to the data that I could manually delete afterwards that would be ideal.
You cannot have that. std::vector always destroys its data, and it is not possible to steal the data to the outside of the vector (except into another vector through move or swap).
The whole point of a reference is that it doesn't own the object. It's perfectly valid to use a std::unique_ptr here, which owns the object and can be returned to your caller.
Your function would be defined as follows (I assume a vector of integers), and C++14 or newer:
std::unique_ptr<std::vector<int>> getVector() {
auto vec = std::make_unique<std::vector<int>>(/*any ctor args you want*/);
// for example
vec->push_back(1);
vec->push_back(2);
return vec;
}
A caller can then do as follows:
int main() {
auto vec = getVector();
std::cout << vec->size() << std::endl;
}
and the vector will be safely deleted as the unique_ptr goes out of scope. Note that if you are using C++11, you won't have std::make_unique and will need to do something like:
std::unique_ptr<std::vector<int>> vec(new std::vector<int>(/* ctor args */));
Just write your code like this:
std::vector<blah> my_function_that_returns_a_vector ()
{
std::vector <blah> v;
... code to populate v ...
return v;
}
NVRO will then eliminate the copy. Instead, the vector returned is constructed directly in the caller's stack frame.
It is not possible to preserve the reference to a vector after it goes out of scope because, and you mentioned, it will be deleted. Once the vector is deleted, the memory stored at that address will be inaccessible. Alternatively, you can declare the variable outside of the scope, edit it within the scope. You mention returning by reference - is it possible that you can pass the vector into the function by reference, and simply return void? This way, you can edit the same vector in different scopes.

Memory deallocation inside a member function

I was thinking about a this situation not for a real implementation but to understand better how pointers works.
class foo(){
foo();
~foo();
void doComplexThings(const std::vector<int*>& v){
int* copy;
for(int i = 0; i < v.size(); i++){
copy = v[i];
// do some stuffs
}
}
}
main(){
std::vector<int*> myVector; // suppose we have 100 elements
doComplexThings(myVector);
for(int i = 0; i < myVector.size(); i++){
delete myVector[i];
}
myVector.clear();
}
Ok, I know that have no sense to copy v[i] inside an other pointer, but I was thinking: copy do a memory leak?
After the execution of doComplexThings(), copy will continue to exist and will occupy space in the heap?
After deleting all elements it will continue to exist and point to a deallocated memory?
So logically if I do this things with complex objects I'll keep occupy the memory with unreference object? Or copy is saved in the stack because I don't use new? And at the end of doComplexThings it will be deleted?
I'm a bit confused, thanks!
There is some confusion on the topic of pointers in the C++ community. While it is true that smart pointers have been added to the library to alleviate problems with dynamic memory allocation, raw pointers are not obsolete. In fact, whenever you want to inspect another object without owning it, you should use a reference or raw pointer, depending on which suits your needs. If the concept of ownership is unclear to you, think of an object as being owned by another object if the latter is responsible for cleaning up afterwards (deleting the former).
For example most uses of new and delete should be replaces with the following (omitting std for brevity):
{
auto ptr_to_T = make_unique<T>(//constructor params);
do_stuff_with_smart_ptr(ptr_to_T);
do_stuff_with_T(*ptr_to_T);
do_stuff_with_raw_ptr(ptr_to_T.get());
} // automatic release of memory allocated with make_unique()
Notice how a function that takes a T* doesn't need a smart pointer if it doesn't keep a copy of the T* it is given, because it doesn't affect the lifetime of the object. The object is guaranteed to be alive past the return point of do_stuff_with_T() and its function signature signals that it doesn't own the object by taking a raw pointer.
On the other hand, if you need to pass the pointer to an object that is allowed to keep the pointer and reference it later, it is unclear when the object will need to be destroyed and most importantly by whom. This is solved via a shared pointer.
ClassThatNeedsSharedOwnership shared_owner;
{
auto ptr_to_T = make_shared<T>(//constructor params);
shared_owner.set_T(ptr_to_T);
// do a lot of stuff
}
// At this point ptr_to_T is destroyed, but shared_owner might keep the object alive
So how does the above factor in to your code. First of all, if the vector is supposed to own (keep alive) the ints it points to, it needs to hold unique_ptr<int> or shared_ptr<int>. If it is just pointing to ints held by something else, and they are guaranteed to be alive until after the vector is destroyed, you are fine with int*. In this case, it should be evident that a delete is never necessary, because by definition your vector and the function working on the vector are not responsible for cleaning-up!
Finally, you can make your code more readable by changing the loop to this (C++11 which you've tagged in the post):
for (auto copy : v){
// equivalent to your i-indexed loop with copy = v[i];
// as long as you don't need the value of i
do_stuff_to_int_ptr(copy);
// no delete, we don't own the pointee
}
Again this is only true if some other object holds the ints and releases them, or they are on the stack but guaranteed to be alive for the whole lifetime of vector<int*> that points to them.
No additional memory is allocated on the heap when you do this:
copy = v[i];
variable copy points to the same address as v[i], but no additional array is allocated, so there would be no memory leak.
A better way of dealing with the situation is to avoid raw pointers in favor of C++ smart pointers or containers:
std::vector<std::vector<int>> myVector;
Now you can remove the deletion loop, which is an incorrect way of doing it for arrays allocated with new int[length] - it should use delete[] instead:
delete[] myVector[i];
Basically you're illustrating the problem with C pointers which lead to the introduction of C++ unique and shared pointers. If you pass a vector of allocated pointers to an opaque member function, you've no way of knowing whether that function hangs onto them or not, so you don't know whether to delete the pointer. In fact in your example you don't seem to, "copy" goes out of scope.
The real answer is that you should only seldom use allocated pointers in C++ at all. The stl vector will serve as a safer, easier to use version of malloc / new. Then you should pass them about as const & to prevent functions from changing them. If you do need an allocated pointer, make one unique_ptr() and then you know that the unique_ptr() is the "owner" of the memory.

Do containers (sets, vectors, etc) need to be created using the new keyword in order persist across functions?

I've been working on a school assignment that makes pretty heavy use of vectors, sets, stacks and queues.
What is the difference between Foo and Bar, especially when passing Foo and Bar between functions? When would it be safe to call delete on Bar, if ever? I'm guess it's never safe to call delete on Bar unless everything in that vector has been moved? If I return Foo, wont it (and its contents) be deleted when the function exits?
vector<Line *> Foo;
and:
vector<Line *> * Bar = new vector<Line *>();
Similary, lets say I have a function:
vector<Line *> BSTIndex::query(string expression)
{
vector<Line *> result; //Holds the lines that match the expression
string query = expression;
queue<string> * output = expressionParser(query);
doSomeStuffWithOutputHere();
return result;
}
And my expressionParser is:
queue<string> * BSTIndex::expressionParser(string query)
{
char * cQuery = new char[100];
strcpy_s(cQuery, 100,query.c_str());
//strcpy(cQuery, query.c_str());
queue<string> * output = new queue<string>(); //Operators go in the queue
stack<string> * s = new stack<string>(); //Operands go on the stack
performSomeMagicOnQueueAndStackHere();
return output;
}
The stack is actually only local to expressionParser so I KNOW I can remove the new keyword from that. The queue however, needs to go back to the query function where it's used but then that's it. Do I HAVE To create a pointer to the queue in this case (I want to say yes because it's going to fall out of scope when expressionParser returns). If I need to create the pointer, then I should call a delete output in my query function to properly get rid of the queue?
My last concern is the vector being returned by query. Should that be left as I have it or should it be a pointer and what's the difference between them? Once I consume that vector (display the information in it) I need it to be removed from memory, however, the pointers contained in the vector are still good and the items being pointed to by them should not be deleted. What's the best approach in this case?
What happens to the contents of containers when you call delete on the container? If the container held pointers, and those pointers are deleted won't that affect other areas of my program?
SO many questions (direct and indirect) crammed into such a small space!
What is the difference between Foo and Bar.
vector<Line*> Foo;
vector<Line*>* Bar = new vector<Line*>();
Foo is an object of automatic (potentially static (but the distinction is not important here)) storage duration. This means it is created at the point of declaration (constructors called) and destroyed when it goes out of scope (destructors called).
Bar on the other hand is a pointer. Pointer have no constructors or destructors and are used to point at other objects (or NULL). Here Bar is initialized to point at an object of dynamic storage duration. This is an object that has to be manually released (otherwise it will leak).
especially when passing Foo and Bar between functions?
When passing Foo (by value) to/from functions the copy constructor is used to make a copy of the original object. Note: The standard explicitly states that copying from a function (via return) can be elided (look up RVO/NRVO) and all modern compilers will remove the extra copy construction and build in place at the return site (but this is an optimization invisible to the user just think of it as a very efficient copy out of a function). The resut of this is that when passed into a function (by value) or returned from a function (by return) you are working on a new object (not the original). This is important because of the side effects of using the object will not affect the original. (see your question below about returning Foo).
When passing Bar (by value) the pointer is copied. But this means that what is pointed at is the same. So modifying an object via the pointer is modifying the original value. This makes passing it as a parameter very cheap (because all you are passing is the address of the object). But it makes returning a value potentially dangerous, this is because you could return the address of an object that has gone out of scope inside the function.
Using pointers in inherently dangerous and modern C++ programs rarely use RAW pointers directly. Pointers are usually wrapped up inside objects that manage the ownership and potentially lifespan of the object (see smart pointers and containers).
When would it be safe to call delete on Bar, if ever?
It is only safe to delete Bar if:
It is NULL
The object it points at has been dynamically allocated via new.
I'm guess it's never safe to call delete on Bar unless everything in that vector has been moved?
It would safe to delete Bar even if it's content had not been moved (though you could leak if the contained pointers were owned by Bar (this is not directly unsafe but can be inconvenient when you run out of space)). This is another reason pointers are rarely used directly, there are no ownership semantics associated with a pointer. This means we can not tell if Bar owns the pointers it holds (it is the responsibility of the owner to call delete on a pointer when it is no longer used).
If I return Foo, wont it (and its contents) be deleted when the function exits?
Yes. But because you return an object it will be copied out of the function. So what you use outside the function is a copy of Foo (Though optimizers may elide the copy because of RVO/NRVO. Not if the copy is elided the destructor is also elided).
Similary, lets say I have a function: query and expressionParser:
vector<Line *> BSTIndex::query(string expression)
{
vector<Line *> result; //Holds the lines that match the expression
string query = expression;
queue<string> * output = expressionParser(query);
doSomeStuffWithOutputHere();
return result;
}
queue<string> * BSTIndex::expressionParser(string query)
{
char* cQuery = new char[100];
strcpy_s(cQuery, 100,query.c_str());
queue<string> * output = new queue<string>(); //Operators go in the queue
stack<string> * s = new stack<string>(); //Operands go on the stack
performSomeMagicOnQueueAndStackHere();
return output;
}
The stack is actually only local to expressionParser so I KNOW I can remove the new keyword from that.
Not only can you but you should. As currently you are leaking this object when it goes out of scope.
The queue however, needs to go back to the query function where it's used but then that's it. Do I HAVE To create a pointer to the queue in this case (I want to say yes because it's going to fall out of scope when expressionParser returns).
No. You can pass the obejct back by value. It will be correctly copied out of the function. If you find that this is expensive (unlikely) then you could create a dynamic object with new and pass it back as a pointer (but you may want to look at smart pointers). Remember that pointers do not indicate that you are the owner so it is unclear who should delete a pointer (or even if it should be deleted). So (if passing a value is too expensive) use a std::auto_ptr<> and pass the pointer back inside it.
If I need to create the pointer, then I should call a delete output in my query function to properly get rid of the queue?
Yes. And No. If you create a dynamic object with new. Then somebody must call delete on it. It is bad C++ style to do this manually. Learn to use smart pointers so that it is done automatically and in an exception safe manor.
My last concern is the vector being returned by query. Should that be left as I have it or should it be a pointer and what's the difference between them?
I would do it like this:
vector<Line> BSTIndex::query(string const& expression)
{
vector<Line> result; // 1 Keep line objects not pointers.
queue<string> output = expressionParser(expression);
doSomeStuffWithOutputHere();
return result;
}
queue<string> BSTIndex::expressionParser(string const& query)
{
char cQuery[100]; // Don't dynamically allocate
// unless somebody takes ownership.
// It would probably be better to use string or vector
// depending on what you want to do.
strcpy_s(cQuery, 100, query.c_str()); // std::string can use the assignment operator.
queue<string> output; // Just build the que and use it.
stack<string> s; // Unless there is a need. Just use a local one.
performSomeMagicOnQueueAndStackHere();
return output;
}
Once I consume that vector (display the information in it) I need it to be removed from memory, however, the pointers contained in the vector are still good and the items being pointed to by them should not be deleted. What's the best approach in this case?
Depends who owns the pointers.
What happens to the contents of containers when you call delete on the container?
If the content of the containers are pointers. Then nothing. The pointers disappear (what they point at is unchanged and unaffected). If the container contains objects (not pointers) then the destructor is called on the objects.
If the container held pointers, and those pointers are deleted won't that affect other areas of my program?
It would. But you would have to call delete manually.
For the most part, what you normally want to do is just create an instance of the object in question, and when you need to return it, return it.
For something like a large container, that can (and often does) sound like it'd be horribly inefficient. In reality, however, it's usually quite efficient. The C++ standard has a couple of clauses to allow what are called Return Value Optimization (RVO) and Named Return Value Optimization (NRVO). Initially, what's in the standard doesn't sound very important -- it just says the compiler doesn't have to call the copy constructor for a returned value, even if the copy constructor has side effects so you can see that it's been omitted.
What this means in reality, however, is that the compiler (which is to say essentially all reasonably current compilers) will actually only create one collection at the highest level in the function call hierarchy where it gets used. When you end up returning the object of that type from some other function, instead of creating a local copy, and then copying it for the return, it'll just generate code in the called function that works directly in the collection in the calling function, so the return basically becomes a nop. As a result, instead of the horribly inefficient copying that it looks like, you end up with a really fast return with no copying at all.
(1) The stack is actually only local to expressionParser so I KNOW I can remove the new keyword
correct
(2) Do I HAVE To create a pointer to the queue in this case. If I need to create the pointer, then I should call a delete output in my query function to properly get rid of the queue?
correct. Here, "creating pointer" doesn't mean again using new and copy all contents. Just assign a pointer to the already created queue<string>. Simply delete output; when you are done with it in your query().
(3) vector being returned by query. Should that be left as I have it or should it be a pointer and what's the difference between them?
I would suggest either you pass the vector<Line*> by non-const reference to your query() and use it or return a vector<Line*>* from your function. Because difference is, if the vector is huge and return by value then it might copy all its content (considering the worst case without optimization)
(4) Once I consume that vector (display the information in it) I need it to be removed from memory, however, the pointers contained in the vector are still good and the items being pointed to by them should not be deleted. What's the best approach in this case?
Pass the vector<Line*> into the function by reference. And retain it in scope until you need it. Once you are done with pointer members 'Line*inside it, justdelete` them
(5) What happens to the contents of containers when you call delete on the container? If the container held pointers?
Nothing happens to the pointer members of the container when it's deleted. You have to explicitly call delete on every member. By the way in your case, you can't delete your vector<Line*> because it's an object not a pointer & when you delete output;, you don't have to worry about contents of queue<> because they are not pointers.
(6) Those pointers are deleted won't that affect other areas of my program?
Deleting a valid pointer (i.e. allocated on heap) doesn't affect your program in any way.
You got a logic problem here - a std::vector (or any container for that matter) of pointers will, at destruction, only kill those pointers, not what they point to. So the following is perfectly fine:
#include <vector>
#include <iostream>
std::vector<int*> GetIntPtrVec(){
std::vector<int*> ret(10); // prepare for 10 pointer;
for(int i=0; i<10; ++i){
ret[i] = new int(i);
}
}
int main(){
std::vector<int*> myvec = GetIntPtrVec(); // copies the return into myvec
// ^^^^^^^^^^^^^^^^^^^^^^
for(int i=0; i<myvec.size(); ++i){
// display and delete again
std::cout << myvec[i] << "\n";
delete myvec[i];
}
std::cin.get();
}
When returning a vector from a function, it gets copied into the receiving variable (marked by the ^ above).
Then for the pointer-to-vector approach, of course you need to delete that pointer again sometime - when you can be sure that nobody uses it anymore. But that same problem also applies for the first approach - when are you gonna delete the pointers inside the returned vector? You have to make sure that there are no dangling pointers, e.g. pointer, which point to your now deleted memory.

Variable Scoping in a method and its persistence in C++

Consider the following public method that adds an integer variable to a vector of ints(private member) in a class in C++.
KoolMethod()
{
int x;
x = 10;
KoolList.Add(x);
}
Vector<int>KoolList;
But is this a valid addition to a vector ??? Upon calling the method, it creates a local variable. The scope of this local variable ends the moment the execution control leaves the method. And since this local variable is allocated on a stack(on the method call), any member of KoolList points to an invalid memory location in deallocated stack which may or may not contain the expected value of x. Is this an accurate description of above mechanism ??
Is there a need for creating an int in heap storage using "new" operator everytime a value needs to be added to the vector like described below ????:
KoolMethod()
{
int *x = new int();
*x = 10;
KoolList.Add(x);
}
Vector<int*>KoolList;
But is this a valid addition to a vector?
Yes, a (standard library) vector stores copies.
Is there a need for creating an int in heap storage using "new" operator
If you don't want the objects to be copied or to work with polymorphic objects (see object slicing) you'd use pointers. In that case you should preferably avoid dealing with deallocation manually and use wrappers (smart pointers or pointer containers) though to get exception safety back.
A Vector<int> (at least if it is std::vector) stores elements by value, so calls to add() creates a copy of the parameter object and stores that copy into the array. Therefore it doesn't matter what happens with the original object, the copy within the vector is alive as long as the vector itself (unless removed or overwritten explicitly, of course).
A Vector<X*> may be more appropriate if you
want to work with polymorphic X objects,
don't want to copy objects of X e.g. because it's expensive or disallowed,
want to share the same objects between different parties.
Of course, none of these applies to int, only to real objects. Still, it is better to store smart pointers in the vector instead of raw pointers, e.g. vector<auto_ptr<X> > or vector<shared_ptr<X> >. These automatically manage the disposal of objects for you.
If you create a vector of ints, it will not be a vector of pointers. The integers are stored by value, no pointers involved, and therefore you won't run into any problems with invalid memory addresses.
Here's an example of code that would cause such a problem:
std::vector<int *> my_list;
void a_method() {
int value = 2; // allocated on the stack
my_list.push_back(&value); // pushes a pointer to the stack... not good
}
Think about this: adding to the standard vector creates copy of added object.
In the first code snippet, you use vector of ints, so you'll add the copy of local int and everything is fine.
In the second code snippet you use vector of pointers to int, so you'll add the copy of a pointer (not the copy of the object this pointer is pointing to). Since the object pointed by the pointer will be still valid after leaving the method (it's initialized using new operator and it's not deleted anywhere) everything will be fine too.

Storing a pointer to an object created in a method

Using C++:
I currently have a method in which if an event occurs an object is created, and a pointer to that object is stored in a vector of pointers to objects of that class. However, since objects are destroyed once the local scope ends, does this mean that the pointer I stored to the object in the vector is now null or undefined? If so, are there any general ways to get around this - I'm assuming the best way would be to allocate on the heap.
I ask this because when I try to access the vector and do operations on the contents I am getting odd behavior, and I'm not sure if this could be the cause or if it's something totally unrelated.
It depends on how you allocate the object. If you allocate the object as an auto variable, (i.e. on the stack), then any pointer to that object will become invalid once the object goes out of scope, and so dereferencing the pointer will lead to undefined behavior.
For example:
Object* pointer;
{
Object myobject;
pointer = &myobject;
}
pointer->doSomething(); // <--- INVALID! myobject is now out of scope
If, however, you allocate the object on the Heap, using the new operator, then the object will remain valid even after you exit the local scope. However, remember that there is no automatic garbage collection in C++, and so you must remember to delete the object or you will have a memory leak.
So if I understand correctly you have described the following scenario:
class MyClass
{
public:
int a;
SomeOtherClass b;
};
void Test()
{
std::vector<MyClass*> v;
for (int i=0; i < 10; ++i)
{
MyClass b;
v.push_back(&b);
}
// now v holds 10 items pointers to strange and scary places.
}
This is definitely bad.
There are two primary alternatives:
allocate the objects on the heap using new.
make the vector hold instances of MyClass (i.e. std::vector<MyClass>)
I generally prefer the second option when possible. This is because I don't have to worry about manually deallocating memory, the vector does it for me. It is also often more efficient. The only problem, is that I would have to be sure to create a copy constructor for MyClass. That means a constructor of the form MyClass(const MyClass& other) { ... }.
If you store a pointer to an object, and that object is destroyed (e.g. goes out of scope), that pointer will not be null, but if you try to use it you will get undefined behavior. So if one of the pointers in your vector points to a stack-allocated object, and that object goes out of scope, that pointer will become impossible to use safely. In particular, there's no way to tell whether a pointer points to a valid object or not; you just have to write your program in such a way that pointers never ever ever point to destroyed objects.
To get around this, you can use new to allocate space for your object on the heap. Then it won't be destroyed until you delete it. However, this takes a little care to get right as you have to make sure that your object isn't destroyed too early (leaving another 'dangling pointer' problem like the one you have now) or too late (creating a memory leak).
To get around that, the common approach in C++ is to use what's called (with varying degrees of accuracy) a smart pointer. If you're new to C++ you probably shouldn't worry about these yet, but if you're feeling ambitious (or frustrated with memory corruption bugs), check out shared_ptr from the Boost library.
If you have a local variable, such as an int counter, then it will be out of scope when you exit the function, but, unless you have a C++ with a garbage collector, then your pointer will be in scope, as you have some global vector that points to your object, as long as you did a new for the pointer.
I haven't seen a situation where I have done new and my memory was freed without me doing anything.
To check (in no particular order):
Did you hit an exception during construction of member objects whose pointers you store?
Do you have a null-pointer in the container that you dereference?
Are you using the vector object after it goes out of scope? (Looks unlikely, but I still have to ask.)
Are you cleaning up properly?
Here's a sample to help you along:
void SomeClass::Erase(std::vector<YourType*> &a)
{
for( size_t i = 0; i < a.size(); i++ ) delete a[i];
a.clear();
}