By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,146 Members | 1,614 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,146 IT Pros & Developers. It's quick & easy.

basic question about std::vector

P: n/a
I am using std::vector in my program:

func()
{
std::vector <CMyClass *> vpMyClass;
vpMyClass.push_back(new CMyClass());
vpMyClass.push_back(new CMyClass());
vpMyClass.push_back(new CMyClass());

//???? Required ??????????????//
delete vpMyClass[0];
delete vpMyClass[1];
delete vpMyClass[2];

}

or vector automatically delete all pointer when it is out of the scope?

Jan 6 '06 #1
Share this Question
Share on Google+
9 Replies


P: n/a
kathy wrote:
I am using std::vector in my program:

func()
{
std::vector <CMyClass *> vpMyClass;
vpMyClass.push_back(new CMyClass());
vpMyClass.push_back(new CMyClass());
vpMyClass.push_back(new CMyClass());

//???? Required ??????????????//
delete vpMyClass[0];
delete vpMyClass[1];
delete vpMyClass[2];

}

or vector automatically delete all pointer when it is out of the scope?


Vector just knows about the value that it's storing - a binary value of
the size of memory addresses on your system. It doesn't know or care
about what that value actually means. So, yes, if you store pointers to
dynamically allocated memory in a vector, you are responsible for
freeing the memory yourself.

Another perspective: If vectors containing pointers somehow knew to free
dynamically allocated objects before deleting the entries, then the
following code would probably crash your system:

func()
{
std::vector<char*> vec;
vec.push_back("a string");
vec.push_back(new char[100]);
vec.push_back(NULL);
}

The second thing that I push is a pointer to dynamically-allocated
memory that must be freed. The first, however, is a pointer to
statically-allocated memory, and attempting to delete it would result in
undefined behaviour. The third points to nothing at all, although I
think that delete is supposed to handle null pointers.

If you must store pointers to dynamically allocated memory in STL
containers (and there are reasons to do so), then you really should
write your own wrapper class that handles both allocations and deletions
itself, to ensure that no pointers to non-dynamic memory get stored, and
that everything is appropriately deleted. Also, if there's a chance of
an exception being thrown in your code, make sure that exceptions can't
result in memory leaks.

Rennie deGraaf
Jan 6 '06 #2

P: n/a
Rennie deGraaf wrote:
kathy wrote:
I am using std::vector in my program:

func()
{
std::vector <CMyClass *> vpMyClass;
vpMyClass.push_back(new CMyClass());
vpMyClass.push_back(new CMyClass());
vpMyClass.push_back(new CMyClass());

//???? Required ??????????????//
delete vpMyClass[0];
delete vpMyClass[1];
delete vpMyClass[2];

}

or vector automatically delete all pointer when it is out of the scope?

Vector just knows about the value that it's storing - a binary value of
the size of memory addresses on your system. It doesn't know or care
about what that value actually means. So, yes, if you store pointers to
dynamically allocated memory in a vector, you are responsible for
freeing the memory yourself.

[snip] If you must store pointers to dynamically allocated memory in STL
containers (and there are reasons to do so), then you really should
write your own wrapper class that handles both allocations and deletions
itself, to ensure that no pointers to non-dynamic memory get stored, and
that everything is appropriately deleted. Also, if there's a chance of
an exception being thrown in your code, make sure that exceptions can't
result in memory leaks.

Rennie deGraaf


Another option is to use a canned smart pointer instead of a raw
pointer to wrap them. Consider boost::shared_ptr, which is also part of
TR1, the proposed extensions to the standard library:

http://boost.org/libs/smart_ptr/smart_ptr.htm

The OP's code would then look like:

#include <boost/shared_ptr.hpp>

void func()
{
std::vector< boost::shared_ptr<CMyClass> > vpMyClass;
vpMyClass.push_back(new CMyClass());
vpMyClass.push_back(new CMyClass());
vpMyClass.push_back(new CMyClass());

// No delete needed
}
Cheers! --M

Jan 6 '06 #3

P: n/a
kathy wrote:
I am using std::vector in my program:

func()
{
std::vector <CMyClass *> vpMyClass;
vpMyClass.push_back(new CMyClass());
vpMyClass.push_back(new CMyClass());
vpMyClass.push_back(new CMyClass());

//???? Required ??????????????//
delete vpMyClass[0];
delete vpMyClass[1];
delete vpMyClass[2];

}
You need to do this since *you* used new, *you* must use delete.
or vector automatically delete all pointer when it is out of the scope?


It frees the memory required for the pointer, but not the memory the
pointer points to.

There may be a problem though, consider:

func() {
std::vector <CMyClass *> vpMyClass;
vpMyClass.push_back(new CMyClass());

// Do something that throws an exception

// this statement not reached, memory leaked.
delete vpMyClass[0];
}

An oft-used solution is to use boost::shared_ptr:

#include <vector>
#include <boost/shared_ptr.hpp>

class CMyClass {};

typedef boost::shared_ptr<CMyClass> spMyClass;

void func() {
std::vector <spMyClass> vpMyClass;
vpMyClass.push_back(spMyClass(new CMyClass()));

// Do something that may throw an exception

//don't need to worry about cleanup, shared_ptr does it.
}

int main() {
func();
}
If you want the container to manage the lifetime, then you can take a
look at boost pointer conatiners:
http://www.boost.org/libs/ptr_contai...tr_vector.html

This will allow your original syntax for adding to the vector:

boost::ptr_vector<CMyClass> vpMyClass;
vpMyClass.push_back(new CMyClass());
Have fun!

Ben Pope
--
I'm not just a number. To many, I'm known as a string...
Jan 6 '06 #4

P: n/a
A nice way to free the memory dynamically allocated in your vector is
described in "Effective C++, second edition" from Meyers:

struct DeleteObject
{
template<typename T>
void operator()(const T* ptr) const
{
delete ptr;
ptr = 0L;
}
};

void func()
{
std::vector <CMyClass *> vpMyClass;
vpMyClass.push_back(new CMyClass());
vpMyClass.push_back(new CMyClass());
vpMyClass.push_back(new CMyClass());

for_each(vpMyClass.begin(), vpMyClass.end(), DeleteObject());
}

It works for any type!

Jan 6 '06 #5

P: n/a
Jeff Lefebvre wrote:
A nice way to free the memory dynamically allocated in your vector is
described in "Effective C++, second edition" from Meyers:

struct DeleteObject
{
template<typename T>
void operator()(const T* ptr) const
{
delete ptr;
ptr = 0L;
}
};

void func()
{
std::vector <CMyClass *> vpMyClass;
vpMyClass.push_back(new CMyClass());
vpMyClass.push_back(new CMyClass());
vpMyClass.push_back(new CMyClass());

for_each(vpMyClass.begin(), vpMyClass.end(), DeleteObject());
}

It works for any type!

I recommend a DeleteObject class that will also Nullify the pointer.
Example code:
class DeleteObject
{
public:
template<typename T>
bool operator()(T& ptr)
{
delete &*ptr;
ptr = NULL;
return true;
}
};

Example usage:
vpMyClass.erase(remove_if(vpMyClass.begin(),
vpMyClass.end(),DeleteObject()), vpMyClass.end());

The above DeleteObject class will also work with any object, and using
the above method would delete and remove the objects from the vector
all in one line of code.

Jan 6 '06 #6

P: n/a

"Rennie deGraaf" <ca.ucalgary.cpsc@degraaf> wrote in message
news:Dgyvf.257925$ki.244533@pd7tw2no...
kathy wrote:
I am using std::vector in my program:

func()
{
std::vector <CMyClass *> vpMyClass;
vpMyClass.push_back(new CMyClass());
vpMyClass.push_back(new CMyClass());
vpMyClass.push_back(new CMyClass());

//???? Required ??????????????//
delete vpMyClass[0];
delete vpMyClass[1];
delete vpMyClass[2];

}

or vector automatically delete all pointer when it is out of the scope?


Vector just knows about the value that it's storing - a binary value of
the size of memory addresses on your system. It doesn't know or care
about what that value actually means. So, yes, if you store pointers to
dynamically allocated memory in a vector, you are responsible for
freeing the memory yourself.

Another perspective: If vectors containing pointers somehow knew to free
dynamically allocated objects before deleting the entries, then the
following code would probably crash your system:

func()
{
std::vector<char*> vec;
vec.push_back("a string");
vec.push_back(new char[100]);
vec.push_back(NULL);
}

The second thing that I push is a pointer to dynamically-allocated
memory that must be freed. The first, however, is a pointer to
statically-allocated memory, and attempting to delete it would result in
undefined behaviour. The third points to nothing at all, although I
think that delete is supposed to handle null pointers.

If you must store pointers to dynamically allocated memory in STL
containers (and there are reasons to do so), then you really should
write your own wrapper class that handles both allocations and deletions
itself, to ensure that no pointers to non-dynamic memory get stored, and
that everything is appropriately deleted. Also, if there's a chance of
an exception being thrown in your code, make sure that exceptions can't
result in memory leaks.

Rennie deGraaf


Please explain this wrapper class you are talking about that handles both
allocations and deletions itself.

I use a lot of vectors or maps of pointers in my program(s). What would
this wrapper class do?

Oh, I think I understand. Instead of storing the pointer to char just store
the wrapper class.

class MyWrapper
{
public:
MyClass *MyObject;
MyWrapper() { MyObject = new MyClass }
~MyWrapper() { delete MyObject; }
};

std::vector <MyWrapper> MyVector;

Interesting. This is a good thought and I think I might implement this.
Then I don't have to iterate and delete the objects of my vector when it
goes out of scope/gets deleted itself.
Jan 7 '06 #7

P: n/a
Jim Langston wrote:
"Rennie deGraaf" <ca.ucalgary.cpsc@degraaf> wrote in message
news:Dgyvf.257925$ki.244533@pd7tw2no...
kathy wrote:
I am using std::vector in my program:

func()
{
std::vector <CMyClass *> vpMyClass;
vpMyClass.push_back(new CMyClass());
vpMyClass.push_back(new CMyClass());
vpMyClass.push_back(new CMyClass());

//???? Required ??????????????//
delete vpMyClass[0];
delete vpMyClass[1];
delete vpMyClass[2];

}

or vector automatically delete all pointer when it is out of the scope?

Vector just knows about the value that it's storing - a binary value of
the size of memory addresses on your system. It doesn't know or care
about what that value actually means. So, yes, if you store pointers to
dynamically allocated memory in a vector, you are responsible for
freeing the memory yourself.

Another perspective: If vectors containing pointers somehow knew to free
dynamically allocated objects before deleting the entries, then the
following code would probably crash your system:

func()
{
std::vector<char*> vec;
vec.push_back("a string");
vec.push_back(new char[100]);
vec.push_back(NULL);
}

The second thing that I push is a pointer to dynamically-allocated
memory that must be freed. The first, however, is a pointer to
statically-allocated memory, and attempting to delete it would result in
undefined behaviour. The third points to nothing at all, although I
think that delete is supposed to handle null pointers.

If you must store pointers to dynamically allocated memory in STL
containers (and there are reasons to do so), then you really should
write your own wrapper class that handles both allocations and deletions
itself, to ensure that no pointers to non-dynamic memory get stored, and
that everything is appropriately deleted. Also, if there's a chance of
an exception being thrown in your code, make sure that exceptions can't
result in memory leaks.

Rennie deGraaf

Please explain this wrapper class you are talking about that handles both
allocations and deletions itself.


There's no easy way (using standard C++) to store objects of different
types derived from the same base class in an STL container. One common
work-around is to store pointers to the base class in the container. If
you must do this, then I reccomend that you wrap your container in a
class that makes copies of objects to insert, returns const references
to objects, deletes everything properly in its destructor, and is very
careful about exceptions. For instance, if I have the following classes:

class Shape;
class Circle : public Shape;
class Square : public Shape;

and you needed to store both Circles and Squares in the same
std::vector, then you could do something like this:

class ShapeVector {
std::vector<Shape*> shapes;
public:
const Shape& getFirst() { return *(shapes[0]); }
void add(Shape& shape) { shapes.push_back(new Shape(shape)); }
~ShapeVector() { for (int i=0; i<shapes.length(); i++) delete
shape[i]; }

This is incomplete and probably won't compile, but hopefully you get the
idea. If it's possible for any of your methods that allocate or free
resources to throw exceptions, make sure that nothing is left hanging
when an exception is thrown.

(For the record, there are apparently ways to solve the problem that I
described without using pointers, by using classes from boost.)

If you're storing objects by pointer because you can't afford the cost
of the STL copying them all the time, you might still use a trick like
this, as long as you can afford the cost of copying them once.

An alternate approach, that may be better in some situations, would be
to use some sort of smart pointer. This would work even if you can't
afford to copy your objects at all, or they aren't copyable. If you're
not trying to use polymorphism, and your objects are cheaply copyable,
them I can't think of any good reason to store pointers to dynamic
memory in a container.

I use a lot of vectors or maps of pointers in my program(s). What would
this wrapper class do?

Oh, I think I understand. Instead of storing the pointer to char just store
the wrapper class.

class MyWrapper
{
public:
MyClass *MyObject;
MyWrapper() { MyObject = new MyClass }
~MyWrapper() { delete MyObject; }
};

std::vector <MyWrapper> MyVector;

Interesting. This is a good thought and I think I might implement this.
Then I don't have to iterate and delete the objects of my vector when it
goes out of scope/gets deleted itself.


This would be a good approach for expensively copyable or uncopyable
objects. Don't bother for cheaply copiable stuff - just store them
directly.

Rennie deGraaf
Jan 7 '06 #8

P: n/a
Ben Pope wrote:
kathy wrote:
I am using std::vector in my program:

func()
{
std::vector <CMyClass *> vpMyClass;
vpMyClass.push_back(new CMyClass());
vpMyClass.push_back(new CMyClass());
vpMyClass.push_back(new CMyClass());

//???? Required ??????????????//
delete vpMyClass[0];
delete vpMyClass[1];
delete vpMyClass[2];

}


You need to do this since *you* used new, *you* must use delete.
or vector automatically delete all pointer when it is out of the scope?


It frees the memory required for the pointer, but not the memory the
pointer points to.

There may be a problem though, consider:

func() {
std::vector <CMyClass *> vpMyClass;
vpMyClass.push_back(new CMyClass());

// Do something that throws an exception

// this statement not reached, memory leaked.
delete vpMyClass[0];
}

An oft-used solution is to use boost::shared_ptr:

#include <vector>
#include <boost/shared_ptr.hpp>

class CMyClass {};

typedef boost::shared_ptr<CMyClass> spMyClass;

void func() {
std::vector <spMyClass> vpMyClass;
vpMyClass.push_back(spMyClass(new CMyClass()));

// Do something that may throw an exception

//don't need to worry about cleanup, shared_ptr does it.
}

int main() {
func();
}
If you want the container to manage the lifetime, then you can take a
look at boost pointer conatiners:
http://www.boost.org/libs/ptr_contai...tr_vector.html

This will allow your original syntax for adding to the vector:

boost::ptr_vector<CMyClass> vpMyClass;
vpMyClass.push_back(new CMyClass());


For a more generic method, you can use cow_ptr and/or copy_ptr smart
pointers.
http://code.axter.com/cow_ptr.h
http://code.axter.com/copy_ptr.h

Both of the above smart pointers can be used without having to create a
clone function, where as the boost pointer containers require
additional clone function logic in order to use it.
Also, (IMO) the cow_ptr/copy_ptr smart pointers are better at catching
slicing then are the boost pointer containers.
Example usage:
vector<cow_ptr<CMyClass> > vpMyClass;
vpMyClass.push_back(new CMyClass);

Jan 7 '06 #9

P: n/a
"Rennie deGraaf" <ca.ucalgary.cpsc@degraaf> wrote in message
news:2KIvf.147236$2k.86845@pd7tw1no...
Jim Langston wrote:
"Rennie deGraaf" <ca.ucalgary.cpsc@degraaf> wrote in message
news:Dgyvf.257925$ki.244533@pd7tw2no...
kathy wrote:

I am using std::vector in my program:

func()
{
std::vector <CMyClass *> vpMyClass;
vpMyClass.push_back(new CMyClass());
vpMyClass.push_back(new CMyClass());
vpMyClass.push_back(new CMyClass());

//???? Required ??????????????//
delete vpMyClass[0];
delete vpMyClass[1];
delete vpMyClass[2];

}

or vector automatically delete all pointer when it is out of the scope?
Vector just knows about the value that it's storing - a binary value of
the size of memory addresses on your system. It doesn't know or care
about what that value actually means. So, yes, if you store pointers to
dynamically allocated memory in a vector, you are responsible for
freeing the memory yourself.

Another perspective: If vectors containing pointers somehow knew to free
dynamically allocated objects before deleting the entries, then the
following code would probably crash your system:

func()
{
std::vector<char*> vec;
vec.push_back("a string");
vec.push_back(new char[100]);
vec.push_back(NULL);
}

The second thing that I push is a pointer to dynamically-allocated
memory that must be freed. The first, however, is a pointer to
statically-allocated memory, and attempting to delete it would result in
undefined behaviour. The third points to nothing at all, although I
think that delete is supposed to handle null pointers.

If you must store pointers to dynamically allocated memory in STL
containers (and there are reasons to do so), then you really should
write your own wrapper class that handles both allocations and deletions
itself, to ensure that no pointers to non-dynamic memory get stored, and
that everything is appropriately deleted. Also, if there's a chance of
an exception being thrown in your code, make sure that exceptions can't
result in memory leaks.

Rennie deGraaf

Please explain this wrapper class you are talking about that handles both
allocations and deletions itself.


There's no easy way (using standard C++) to store objects of different
types derived from the same base class in an STL container. One common
work-around is to store pointers to the base class in the container. If
you must do this, then I reccomend that you wrap your container in a
class that makes copies of objects to insert, returns const references
to objects, deletes everything properly in its destructor, and is very
careful about exceptions. For instance, if I have the following classes:

class Shape;
class Circle : public Shape;
class Square : public Shape;

and you needed to store both Circles and Squares in the same
std::vector, then you could do something like this:

class ShapeVector {
std::vector<Shape*> shapes;
public:
const Shape& getFirst() { return *(shapes[0]); }
void add(Shape& shape) { shapes.push_back(new Shape(shape)); }
~ShapeVector() { for (int i=0; i<shapes.length(); i++) delete
shape[i]; }

This is incomplete and probably won't compile, but hopefully you get the
idea. If it's possible for any of your methods that allocate or free
resources to throw exceptions, make sure that nothing is left hanging
when an exception is thrown.

(For the record, there are apparently ways to solve the problem that I
described without using pointers, by using classes from boost.)

If you're storing objects by pointer because you can't afford the cost
of the STL copying them all the time, you might still use a trick like
this, as long as you can afford the cost of copying them once.

An alternate approach, that may be better in some situations, would be
to use some sort of smart pointer. This would work even if you can't
afford to copy your objects at all, or they aren't copyable. If you're
not trying to use polymorphism, and your objects are cheaply copyable,
them I can't think of any good reason to store pointers to dynamic
memory in a container.

I use a lot of vectors or maps of pointers in my program(s). What would
this wrapper class do?

Oh, I think I understand. Instead of storing the pointer to char just
store
the wrapper class.

class MyWrapper
{
public:
MyClass *MyObject;
MyWrapper() { MyObject = new MyClass }
~MyWrapper() { delete MyObject; }
};

std::vector <MyWrapper> MyVector;

Interesting. This is a good thought and I think I might implement this.
Then I don't have to iterate and delete the objects of my vector when it
goes out of scope/gets deleted itself.


This would be a good approach for expensively copyable or uncopyable
objects. Don't bother for cheaply copiable stuff - just store them
directly.


Actually, I store vectors of pointers for 2 different reasons.
The first one is polymorphism.
The second one is becuase I'm using a header to a dll that has objects I
want to store that don't follow the rule of three and aren't copyable.
Hence I store the pointers.
Jan 8 '06 #10

This discussion thread is closed

Replies have been disabled for this discussion.