New Operator With Vectors - c++

These questions are relatively straight forward. When using vectors, should I use the new operator when pushing back a new element? And which release method should I call? Here's what I mean:
// Release method: 1.
void ReleaseMethodOne( vector< int * > &ThisVector )
{
// Clear out the vector.
ThisVector.clear( );
return;
}
// Release method: 2.
void ReleaseMethodTwo( vector< int * > &ThisVector )
{
// Clear out the vector.
for( unsigned uIndex( 0 ); uIndex < ThisVector.size( ); uIndex++ )
{
delete ThisVector.at( uIndex );
}
return;
}
int main( )
{
vector< int * > Vector;
// Add a new element.
Vector.push_back( new int( 2 ) );
// More code...
// Free the elements before exiting. Which method should I call here?
ReleaseMethodOne( Vector ); // This one?
ReleaseMethodTwo( Vector ); // Or this one?
return 0;
}
I've started learning vectors not long ago and the book I was learning from said that the vector's clear( ) method called each of the elements destructor. Do this apply to the new operator?

STL containers store copies of the objects you give to them, pointers in your example. They never release any memory you explicitly allocated. You have to deallocate that memory yourself, so the second "release" method should be used.
Of course, you don't need to new every int. Just use vector<int> instead - you won't have to deal with manual memory management at all.

The clear method will indeed call destructors. However, your vector is storing pointers, and the destructor for pointers is a trivial no-op. It does not call delete.
Therefore, simply calling clear will not free the memory for all the int objects you allocated with new. You need to delete them.
If you use a smart pointer instead of an ordinary pointer, then the pointed-at objects will get freed at the appropriate time without you having to do anything special.

For what you are doing there you would need to use ReleaseMethodTwo. What it means by saying that it calls the element's destructor is that contained classes (not contained pointers) will lose scope and have their destructors called.
No STL container will ever call delete for you, so far as I know. If you allocate and pass in a pointer, you will need to deallocate.

You should use ReleaseMethodTwo(), because if you've allocated the memory, then it's your responsibility to delete it.
std::vector::clear() only erases the elements from the vector. It doesn't call delete on the elements being erased!

As answered by others, vector does call the destructor of each element. In your case, the elements are pointers and hence it will not free the memory.
For your application, the best choice is to use a reference counting smart pointer like boost:shared_ptr. Once there are no more references pointing to the elements (like the example you had written), the memory will be freed automagically.
PS: Do not use a "non-reference counting" smart pointer like std::auto_ptr with vector.

if you are using vactor<int *> than you'll have a vector of pointers and you have to allocate memory for each elements and free this memory yourself also. It doesn't make much sense to use vector of pointers unless the size of type you want to store in the vector is quite big.
Actually when you do vector<T>::push_back(val) is it going to store a copy of val using a copy constructor T::T(T &orig) and call destructor for all elements when you do clear()

Related

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.

Freeing last element of a dynamic array

I have
int * array=new int[2];
and I would like to free the memory of the last element, thus reducing the allocated memory to only 1 element. I tried to call
delete array+1;
but it gives error
*** glibc detected *** skuska:
free(): invalid pointer: 0x000000000065a020 *
Can this be done in C++03 without explicit reallocation?
Note: If I wanted to use a class instead a primitive datatype (like int), how can I free the memory so that the destructor of the class is called too?
Note2: I am trying to implement vector::pop_back
Don't use new[] expression for this. That's not how vector works. What you do is allocate a chunk of raw memory. You could use malloc for this, or you could use operator new, which is different from the new expression. This is essentially what the reserve() member function of std::vector does, assuming you've used the default allocator. It doesn't create any actual objects the way the new[] expression does.
When you want to construct an element, you use placement new, passing it a location somewhere in the raw memory you've allocated. When you want to destoy an element, you call its destructor directly. When you are done, instead of using the delete[] expression, you use operator delete if you used operator new, or you use free() if you used malloc.
Here's an example creating 10 objects, and destoying them in reverse order. I could destroy them in any order, but this is how you would do it in a vector implementation.
int main()
{
void * storage = malloc(sizeof(MyClass) * 10);
for (int i=0; i<10; ++i)
{
// this is placement new
new ((MyClass*)storage + i) MyClass;
}
for (int i=9; i>=0; --i)
{
// calling the destructor directly
((MyClass*)storage + i)->~MyClass();
}
free(storage);
}
pop_back would be implemented by simply calling the destructor of the last element, and decrementing the size member variable by 1. It wouldn't, shouldn't (and couldn't, without making a bunch of unnecessary copies) free any memory.
There is no such option. Only way to resize array is allocate new array with size old_size - 1, copy content of old array and then delete old array.
If you want free object memory why not create array of pointers?
MyClass **arr = new MyClass*[size];
for(int i = 0; i < size; i++)
arr[i] = new MyClass;
// ...
delete arr[size-1];
std::vector::pop_back doesn't reallocate anything — it simply updates the internal variable determining data size, reducing it by one. The old last element is still there in memory; the vector simply doesn't let you access it through its public API. *
This, as well as growing re-allocation being non-linear, is the basis of why std::vector::capacity() is not equivalent to std::vector::size().
So, if you're really trying to re-invent std::vector for whatever reason, the answer to your question about re-allocation is don't.
* Actually for non-primitive data types it's a little more complex, since such elements are semantically destroyed even though their memory will not be freed.
Since you are using C++03, you have access to the std::vector data type. Use that and it's one call:
#include <vector>
//...
std::vector<int> ary(3);
//...
ary.erase(ary.begin() + (ary.size() - 1));
or
#include <vector>
//...
std::vector<int> ary(3);
//...
ary.pop_back();
EDIT:
Why are you trying to re-invent the wheel? Just use vector::pop_back.
Anyway, the destructor is called on contained data types ONLY if the contained data type IS NOT a pointer. If it IS a pointer you must manually call delete on the object you want to delete, set it to nullptr or NULL (because attempting to call delete on a previously deleted object is bad, calling delete on a null pointer is a non-op), then call erase.

C++ delete vector, objects, free memory

I am totally confused with regards to deleting things in C++. If I declare an array of objects and if I use the clear() member function. Can I be sure that the memory was released?
For example :
tempObject obj1;
tempObject obj2;
vector<tempObject> tempVector;
tempVector.pushback(obj1);
tempVector.pushback(obj2);
Can I safely call clear to free up all the memory? Or do I need to iterate through to delete one by one?
tempVector.clear();
If this scenario is changed to a pointer of objects, will the answer be the same as above?
vector<tempObject> *tempVector;
//push objects....
tempVector->clear();
You can call clear, and that will destroy all the objects, but that will not free the memory. Looping through the individual elements will not help either (what action would you even propose to take on the objects?) What you can do is this:
vector<tempObject>().swap(tempVector);
That will create an empty vector with no memory allocated and swap it with tempVector, effectively deallocating the memory.
C++11 also has the function shrink_to_fit, which you could call after the call to clear(), and it would theoretically shrink the capacity to fit the size (which is now 0). This is however, a non-binding request, and your implementation is free to ignore it.
There are two separate things here:
object lifetime
storage duration
For example:
{
vector<MyObject> v;
// do some stuff, push some objects onto v
v.clear(); // 1
// maybe do some more stuff
} // 2
At 1, you clear v: this destroys all the objects it was storing. Each gets its destructor called, if your wrote one, and anything owned by that MyObject is now released.
However, vector v has the right to keep the raw storage around in case you want it later.
If you decide to push some more things into it between 1 and 2, this saves time as it can reuse the old memory.
At 2, the vector v goes out of scope: any objects you pushed into it since 1 will be destroyed (as if you'd explicitly called clear again), but now the underlying storage is also released (v won't be around to reuse it any more).
If I change the example so v becomes a pointer to a dynamically-allocated vector, you need to explicitly delete it, as the pointer going out of scope at 2 doesn't do that for you. It's better to use something like std::unique_ptr in that case, but if you don't and v is leaked, the storage it allocated will be leaked as well. As above, you need to make sure v is deleted, and calling clear isn't sufficient.
vector::clear() does not free memory allocated by the vector to store objects; it calls destructors for the objects it holds.
For example, if the vector uses an array as a backing store and currently contains 10 elements, then calling clear() will call the destructor of each object in the array, but the backing array will not be deallocated, so there is still sizeof(T) * 10 bytes allocated to the vector (at least). size() will be 0, but size() returns the number of elements in the vector, not necessarily the size of the backing store.
As for your second question, anything you allocate with new you must deallocate with delete. You typically do not maintain a pointer to a vector for this reason. There is rarely (if ever) a good reason to do this and you prevent the vector from being cleaned up when it leaves scope. However, calling clear() will still act the same way regardless of how it was allocated.
if I use the clear() member function. Can I be sure that the memory was released?
No, the clear() member function destroys every object contained in the vector, but it leaves the capacity of the vector unchanged. It affects the vector's size, but not the capacity.
If you want to change the capacity of a vector, you can use the clear-and-minimize idiom, i.e., create a (temporary) empty vector and then swap both vectors.
You can easily see how each approach affects capacity. Consider the following function template that calls the clear() member function on the passed vector:
template<typename T>
auto clear(std::vector<T>& vec) {
vec.clear();
return vec.capacity();
}
Now, consider the function template empty_swap() that swaps the passed vector with an empty one:
template<typename T>
auto empty_swap(std::vector<T>& vec) {
std::vector<T>().swap(vec);
return vec.capacity();
}
Both function templates return the capacity of the vector at the moment of returning, then:
std::vector<double> v(1000), u(1000);
std::cout << clear(v) << '\n';
std::cout << empty_swap(u) << '\n';
outputs:
1000
0
Move semantics allows for a straightforward way to release memory, by simply applying the assignment (=) operator from an empty rvalue:
std::vector<int> vec(100, 0);
std::cout << vec.capacity(); // 100
vec = vector<int>(); // Same as "vector<int>().swap(vec)";
std::cout << vec.capacity(); // 0
It is as much efficient as the "swap()"-based method described in other answers (indeed, both are conceptually doing the same thing). When it comes to readability, however, the assignment version makes a better job.
You can free memory used by vector by this way:
//Removes all elements in vector
v.clear()
//Frees the memory which is not used by the vector
v.shrink_to_fit();
If you need to use the vector over and over again and your current code declares it repeatedly within your loop or on every function call, it is likely that you will run out of memory. I suggest that you declare it outside, pass them as pointers in your functions and use:
my_arr.resize()
This way, you keep using the same memory sequence for your vectors instead of requesting for new sequences every time.
Hope this helped.
Note: resizing it to different sizes may add random values. Pass an integer such as 0 to initialise them, if required.

Destructing the Vector contents in C++

I have a std::vector of Element*. When will the destructor be called.
How is it different if it is a vector of Element
std::vector<Element*> vect;
..
struct Element
{
Record *elm;
Element(Record *rec)
{
elm = new Record();
//...copy from rec
}
~Element()
{
delete elm;
}
};
I am using the vector as follows:
Element *copyElm = new Element(record);
vect.push_back(copyElm);
In the above code, how can I ensure there's no leak.
You could use a reference-counting pointer-wrapper class in your array, and the items will automatically get deleted whenever there are no more references to them. One such class is boost::shared_ptr. You will also find it in some compiler's shipping C++ libraries because it is being added to a future version of C++.
std::vector<boost::shared_ptr<Element> > vect;
These classes wrap operator ->, etc, so you can use them in most of the same ways that you'd used a normal pointer.
http://www.boost.org/doc/libs/1_45_0/libs/smart_ptr/shared_ptr.htm
Whenever you free the class Element instance yourself. The vector will free the vector elements (the pointers), but not the class Element objects pointed to. After all, the vector has no way to know if you have other pointers to the same object.
vector will call release the memory of the object it is holding (i.e. pointers) but will not release the memory of the object it is pointing to. You need to release the memory of the Element object yourself. If it was a vector<Element> then whenever you do a push_back a copy of the element is inserted into the vector. vector guarntess that it will release the memory allocated to this copied object. But be aware with the current definition of Element you will get a seg fault as you have not defined the copy ctor and assignment operator.
EDIT
If you for some reason don't want to use smart pointers, then only option is to write a release function which goes through the entire vector and calls the delete on the stored pointer.
In a vector of Element, the destructor is called a lot. Whenever a node is assigned, the vector is sized down, the vector has to move in memory, or the vector goes out of scope/is destroyed, destructors are called on the elements before they are changed/discarded. Also, the copy constructor is called for assignment, and the default constructor is called to initialize each entry. Sorting such a vector will involve a lot of both copying and destroying.
In a vector of Element* it is never called, unless you call delete yourself.
Take a look at Boost shared_ptr for a saner solution, or unique_ptr if you have a compiler with relatively new features.
Destroying a pointer is always a no-op, and there are several good reasons why.

How do stl containers get deleted?

How does container object like vector in stl get destroyed even though they are created in heap?
EDIT
If the container holds pointers then how to destroy those pointer objects
An STL container of pointer will NOT clean up the data pointed at. It will only clean up the space holding the pointer. If you want the vector to clean up pointer data you need to use some kind of smart pointer implementation:
{
std::vector<SomeClass*> v1;
v1.push_back(new SomeClass());
std::vector<boost::shared_ptr<SomeClass> > v2;
boost::shared_ptr<SomeClass> obj(new SomeClass);
v2.push_back(obj);
}
When that scope ends both vectors will free their internal arrays. v1 will leak the SomeClass that was created since only the pointer to it is in the array. v2 will not leak any data.
If you have a vector<T*>, your code needs to delete those pointers before delete'ing the vector: otherwise, that memory is leaked.
Know that C++ doesn't do garbage collection, here is an example of why (appologies for syntax errors, it has been a while since I've written C++):
typedef vector<T*> vt;
⋮
vt *vt1 = new vt, *vt2 = new vt;
T* t = new T;
vt1.push_back(t);
vt2.push_back(t);
⋮
delete vt1;
The last line (delete vt1;) clearly should not delete the pointer it contains; after all, it's also in vt2. So it doesn't. And neither will the delete of vt2.
(If you want a vector type that deletes pointers on destroy, such a type can of course be written. Probably has been. But beware of delete'ing pointers that someone else is still holding a copy of.)
When a vector goes out of scope, the compiler issues a call to its destructor which in turn frees the allocated memory on the heap.
This is somewhat of a misnomer. A vector, as with most STL containers, consists of 2 logical parts.
the vector instance
the actual underlying array implementation
While configurable, #2 almost always lives on the heap. #1 however can live on either the stack or heap, it just depends on how it's allocated. For instance
void foo() {
vector<int> v;
v.push_back(42);
}
In this case part #1 lives on the stack.
Now how does #2 get destroyed? When a the first part of a vector is destroyed it will destroy the second part as well. This is done by deleting the underlying array inside the destructor of the vector class.
If you store pointers in STL container classes you need to manually delete them before the object gets destroyed. This can be done by looping through the whole container and deleting each item, or by using some kind of smart pointer class. However do not use auto_ptr as that just does not work with containers at all.
A good side effect of this is that you can keep multiple containers of pointers in your program but only have those objects owned by one of those containers, and you only need to clean up that one container.
The easiest way to delete the pointers would be to do:
for (ContainerType::iterator it(container.begin()); it != container.end(); ++it)
{
delete (*it);
}
Use either smart pointers inside of the vector, or use boost's ptr_vector. It will automatically free up the allocated objects inside of it. There are also maps, sets, etc.
http://www.boost.org/doc/libs/1_37_0/libs/ptr_container/doc/ptr_vector.html
and the main site:
http://www.boost.org/doc/libs/1_37_0/libs/ptr_container/doc/ptr_container.html
As with any other object in the heap, it must be destroyed manually (with delete).
To answer your first question:
There's nothing special about STL classes (I hope). They function exactly like other template classes. Thus, they are not automatically destroyed if allocated on the heap, because C++ has no garbage collection on them (unless you tell it to with some fancy autoptr business or something). If you allocate it on the stack (without new) it will most likely be managed by C++ automatically.
For your second question, here's a very simple ArrayOfTen class to demonstrate the basics of typical memory management in C++:
/* Holds ten Objects. */
class ArrayOfTen {
public:
ArrayOfTen() {
m_data = new Object[10];
}
~ArrayOfTen() {
delete[] m_data;
}
Object &operator[](int index) {
/* TODO Range checking */
return m_data[index];
}
private:
Object *m_data;
ArrayOfTen &operator=(const ArrayOfTen &) { }
};
ArrayOfTen myArray;
myArray[0] = Object("hello world"); // bleh
Basically, the ArrayOfTen class keeps an internal array of ten Object elements on the heap. When new[] is called in the constructor, space for ten Objects is allocated on the heap, and ten Objects are constructed. Simiarly, when delete[] is called in the destructor, the ten Objects are deconstructed and then the memory previously allocated is freed.
For most (all?) STL types, resizing is done behind the scenes to make sure there's enough memory set asside to fit your elements. The above class only supports arrays of ten Objects. It's basically a very limiting typedef of Object[10].
To delete the elements pointed at, I wrote a simple functor:
template<typename T>
struct Delete {
void operator()( T* p ) const { delete p; }
};
std::vector< MyType > v;
// ....
std::for_each( v.begin(), v.end(), Delete<MyType>() );
But you should fallback on shared pointers when the vector's contents are to be ... ehm... shared. Yes.
A functor that deletes pointers from STL sequence containers
The standard STL containers place a copy of the original object into the container, using the copy constructor. When the container is destroyed the destructor of each object in the container is also called to safely destroy the object.
Pointers are handled the same way.
The thing is pointers are POD data. The copy constructor for a pointer is just to copy the address and POD data has no destructor. If you want the container to manage a pointer you need to:
Use a container of smart pointers. (eg shared pointer).
Use a boost ptr container.
I prefer the pointer container:
The pointer containers are the same as the STL containers except you put pointers into them, but the container then takes ownership of the object the pointer points at and will thus deallocate the object (usually by calling delete) when the container is destroyed.
When you access members of a ptr container they are returned via reference so they behave just like a standard container for use in the standard algorithms.
int main()
{
boost::ptr_vector<int> data;
data.push_back(new int(5));
data.push_back(new int(6));
std::cout << data[0] << "\n"; // Prints 5.
std::cout << data[1] << "\n"; // Prints 6.
} // data deallocated.
// This will also de-allocate all pointers that it contains.
// by calling delete on the pointers. Therefore this will not leak.
One should also point out that smart pointers in a container is a valid alternative, unfortunately std::auto_ptr<> is not a valid choice of smart pointer for this situation.
This is because the STL containers assume that the objects they contain are copyable, unfortunately std::auto_ptr<> is not copyable in the traditional sense as it destroys the original value on copy and thus the source of the copy can not be const.
STL containers are like any other objects, if you instantiate one it is created on the stack:
std::vector<int> vec(10);
Just like any other stack variable, it only lives in the scope of the function it is defined in, and doesn't need to be manually deleted. The destructor of STL containers will call the destructor of all elements in the container.
Keeping pointers in a container is a dicey issue. Since pointers don't have destructors, I would say you would never want to put raw pointers into an STL container. Doing this in an exception safe way will be very difficult, you'd have to litter your code with try{}finally{} blocks to ensure that the contained pointers are always deallocated.
So what should you put into containers instead of raw pointers? +1 jmucchiello for bringing up boost::shared_ptr. boost::shared_ptr is safe to use in STL containers (unlike std::auto_ptr). It uses a simple reference counting mechanism, and is safe to use for data structures that don't contain cycles.
What would you need for data structures that contain cycles? In that case you probably want to graduate to garbage collection, which essentially means using a different language like Java. But that's another discussion. ;)