vector<char*> x;
I have many vectors in my code. However, I need to delete them to minimize memory usage. I know there is a solution like using a "shared_array" but I am not permitted to import any other library. Is there any good solution to prevent memory leak after using vectors?
In your code snippet, you are using a vector of char pointers. I assume that those pointers are allocated via new, and they need to be freed via delete. If the vector goes out of scope, it will be freed, but all those char arrays won't get freed. You need to free them manually.
An alternative would be to use std::string, specifically vector<std::string>. In this way, when the vector goes out of scope, all the strings will be automatically deleted.
C++11 has support for smart pointer objects, such as shared_ptr, so you don't have to use Boost (or anything else).
As johnathon said, you can then just wrap the char * with a smart pointer et voilĂ , you don't have to worry about it anymore.
std::vector<std::unique_ptr<char*>> x;
or
std::vector<std::shared_ptr<char*>> x;
When the element is removed from the vector in either way (.delete(), .erase(), ...) or simply when vector is destroyed, you buffers will be freed.
If your STL implementation or compiler does not support this C++11 feature yet, you can also roll your own smart pointer type, it shouldn't be too hard. See for example this tutorial.
You may use
//Create
vector<char*>* _vec = new vector<char*>(5);
//Fill with something
for(unsigned int i=0; i<_vec->size(); ++i)
(*_vec)[i] = new char[100];
....
//Delete
for(unsigned int i=0; i<_vec->size(); ++i)
delete[] (*_vec)[i]; //Deleting array of char
delete _vec; //but not delete[] as we deleting only one instance of vector
Related
I have this:
std::vector<Pair *> *artistAttributes;
where Pair is a class, how can I add an element into this pointer?
I know how to access this if it was just a std::vector like so,
std::vector<Pair *> artistAttributes;
But I am unfamiliar with how to add elements into this since I am very new to pointers.
I am very knew to pointers.
There is a semantic difference between pointers that just point to objects on the automatic-storage ("stack") and pointers to objects on the free-store ("heap") in that pointers to objects on the heap must at some point be used to deallocate (delete/delete[]) the memory earlier allocated with new (or new[]).
This is not just easily forgotten but cannot be done when an exception is thrown between allocation and deallocation. To make that simpler, smart pointers were invented which follow the RAII/RDID-idiom ("Resource Acquisition Is Initialisation/Resource Destruction is Deletion"): Raw pointers are encapsulated in Objects that manage the lifetime of the resource they handle.
This makes it possible in many circumstances to avoid following the Rule of 3/5 (which is more a Rule of the Big Four (and a half) in modern C++) but use the Rule of Zero instead.
Also, there is no real point in having a pointer to a std::vector<> since vectors are cheap to copy (compared to the inconvenience of having to manage dynamically allocated memory).
So instead of
std::vector<Pair *> *artistAttributes;
better use
std::vector<std::shared_ptr<Pair>> artistAttributes;
Normally you access a member of an object with the . operator. If you wanna access the member of a pointer to an object you use the -> operator instead.
So you can modify the vector with artistAttributes->push_back() (to add a new element) or artistAttributes->at() (to modify an existing element). Equivalently you can also do (*artistAttributes).push_back() and (*artistAttributes).at().
See this:
std::vector<Pair*> *artistAttributes;
artistAttributes = new std::vector<Pair*>;
artistAttributes->push_back(new Pair())
...
for(int i=0; i<artistAttributes->size(); i++)
delete (*artistAttributes)[i] // Don't forget
delete artistAttributes; // Don't forget
In comparison to:
std::vector<Pair*> artistAttributes;
//artistAttributes = new std::vector<Pair*>; // no needed
artistAttributes.push_back(new Pair()) // use . instead of ->
...
for(int i=0; i<artistAttributes.size(); i++)
delete artistAttributes[i] // Don't forget
and in comparison to:
std::vector<Pair> artistAttributes;
//artistAttributes = new std::vector<Pair*>; // no needed
artistAttributes.push_back(Pair())
So, I have dynamically assigned memory to a 2D array:
int **paMatrix = new int*[r];
for(int i=0; i<r; i++)
paMatrix[i] = new int[c];
Assume that my code has already defined r and c. Now I want to free the memory again. If paMatrix was single-indexed, the delete[] paMatrix; would be enough. Is it also enough in this case, or do I have to write
for(int i=0; i<r; i++)
delete[] paMatrix[i];
delete[] paMatrix;
In case I need to call delete once for each new statement, is there a way to rewrite my code so that I only need a single delete statement?
In general, you need to match every new with a delete so if, as here, you're juggling a whole array of raw pointers, you will indeed need to delete each in turn.
This can be a serious hassle if the code between new and delete isn't straightforward, and almost impossible to ensure if it might throw exceptions. For that reason, you should always use RAII types such as containers and smart pointers to manage dynamic resources. In this case, vector<vector<int>> might be an appropriate choice.
I guess the real question is "What does delete and delete[] really do behind the scene?"
If the object type has a non-trivial destructor, it calls that destructor on each object before deallocating the memory. Thus RAII types will automatically release whatever resource they manage through their destructor; but raw pointers don't have destructors, so deleting them will not free any memory that they point to.
As said, in c++ one rarely has more then one indirection through pointers. In a matter of fact, in c++ pointers are avoided whenever possible.
In case I need to call delete once for each new statement, is there a way to rewrite my code so that I only need a single delete statement?
One way would be :
int *paMatrix = new int[r*c];
but then you need to play with indexes.
Another solution (without pointers) without even one delete statement is to use std::vector :
std::vector< std::vector< int > > paMatrix( r, std::vector< int >( c, 0 ) );
You need
for(int i=0; i<r; i++)
delete[] paMatrix[i];
delete[] paMatrix;
There's no way around, except smart pointers etc.
As described in the other answers here, you need to match calls to new with calls to delete.
However if you were willing to change your conception of a 2d array, you can simplify it considerably. For example if it truly a matrix of r x c size you could allocate it as a single array of r*c in size:
int* paMatrix = new int[r*c];
Then you would be able to delete it in a single step.
The tradeoff would be having to index the array using something like paArray[x+c*y] instead of the more natural paArray[x][y].
Besides a lot of member functions, my Graph class has 3 main members: a vector of pointers to its vertices, called "vertex", a vector of pointers to its edges, called "edge", and an integer counter variable. I started/attempted to write the destructor to deallocate the memory from the vectors, but I'm not sure if I am doing it correctly. And what do I do about the counter? I tried to say "delete counter," but it's not a pointer (oops).
Graph<Object,Weight>::~Graph(){
for(unsigned int i=0; i<vertex.size(); ++i){
delete vertex[i]; }
for(unsigned int j=0; j<edge.size(); ++j){
delete edge[j]; }
//counter?
}
Deleting depends on the way you allocated, see The difference between delete and delete [] in C++
As for your int member, since you didn't dynamically allocate it (you didn't use new) you don't have to delete it.
Assuming the type of vertex is std::vector<Vertex*> and you create the vector as follows:
vertex.push_back( new Vertex );
your clean up code looks correct.
But, I urge you not to do this. Declare vertex as std::vector<std::unique_ptr<Vertex>> and you don't need to worry about deleteing the individual vector members anymore.
If you're using Boost, you could also make vertex a boost::ptr_vector.
As for the counter variable, unless you're newing the counter somewhere during class construction, you don't need to delete it.
is counter a plain ordinary int variable? If so, you're not in charge of its lifetime.
The delete keyword is only to be used when you've created an object with the new keyword. (And even then, only when there isn't something else in your program, such as shared_ptr which is doing the delete for you)
When using new/delete you're taking over from the language and managing the lifetime/existance of an object yourself. ordinary variables are created and destroyed automatically, meaning you don't need to worry about them.
You can delete an array of pointers with:
del[] arr; // arr is array of pointers.
Whereas, if counter is from stack, the program will take care of it, and you as programmer don't need to worry about freeing that memory.
I'm assuming that vertex and edge are allocated using new? then what you have written is fine but if you declared your vertex and edge as an array and newed using new [] operator then you need to use the delete [] call instead of delete, if the counter was not declared as a pointer and newed then there is no need to delete the counter.
As a design decision you should consider declaring your vertex and edge objects as boost::shared_ptr or unique_ptr so that they are reference counted and when the Graph object goes out of scope they are automatically cleaned up so you don't even need to flesh out your destructor.
If you have c++11 then you can use the std versions and not need boost like std::shared_ptr and std::unique_ptr.
I come from a java background and there's something I could do in Java that I need to do in C++, but I'm not sure how to do it.
I need to declare an array, but at the moment I don't know the size. Once I know the size, then I set the size of the array. I java I would just do something like:
int [] array;
then
array = new int[someSize];
How do I do this in C++?
you want to use std::vector in most cases.
std::vector<int> array;
array.resize(someSize);
But if you insist on using new, then you have do to a bit more work than you do in Java.
int *array;
array = new int[someSize];
// then, later when you're done with array
delete [] array;
No c++ runtimes come with garbage collection by default, so the delete[] is required to avoid leaking memory. You can get the best of both worlds using a smart pointer type, but really, just use std::vector.
In C++ you can do:
int *array; // declare a pointer of type int.
array = new int[someSize]; // dynamically allocate memory using new
and once you are done using the memory..de-allocate it using delete as:
delete[]array;
Best way would be for you to use a std::vector. It does all you want and is easy to use and learn. Also, since this is C++, you should use a vector instead of an array. Here is an excellent reason as to why you should use a container class (a vector) instead of an array.
Vectors are dynamic in size and grow as you need them - just what you want.
The exact answer:
char * array = new char[64]; // 64-byte array
// New array
delete[] array;
array = new char[64];
std::vector is a much better choice in most cases, however. It does what you need without the manual delete and new commands.
As others have mentioned, std::vector is generally the way to go. The reason is that vector is very well understood, it's standardized across compilers and platforms, and above all it shields the programmer from the difficulties of manually managing memory. Moreover, vector elements are required to be allocated sequentially (i.e., vector elements A, B, C will appear in continuous memory in the same order as they were pushed into the vector). This should make the vector as cache-friendly as a regular dynamically allocated array.
While the same end result could definitely be accomplished by declaring a pointer to int and manually managing the memory, that would mean extra work:
Every time you need more memory, you must manually allocate it
You must be very careful to delete any previously allocated memory before assigning a new value to the pointer, lest you'll be stuck with huge memory leaks
Unlike std::vector, this approach is not RAII-friendly. Consider the following example:
void function()
{
int* array = new int[32];
char* somethingElse = new char[10];
// Do something useful.... No returns here, just one code path.
delete[] array;
delete[] somethingElse;
}
It looks safe and sound. But it isn't. What if, upon attempting to allocate 10 bytes for "somethingElse", the system runs out of memory? An exception of type std::bad_alloc will be thrown, which will start unwinding the stack looking for an exception handler, skipping the delete statements at the end of the function. You have a memory leak. That is but one of many reasons to avoid manually managing memory in C++. To remedy this (if you really, really want to), the Boost library provides a bunch of nice RAII wrappers, such as scoped_array and scoped_ptr.
use std::array when size is known at compile time otherwise use std::vector
#include <array>
constexpr int someSize = 10;
std::array<int, someSize> array;
or
#include <vector>
std::vector<int> array; //size = 0
array.resize(someSize); //size = someSize
Declare a pointer:
int * array;
So I have a pointer to an array of pointers. If I delete it like this:
delete [] PointerToPointers;
Will that delete all the pointed to pointers as well? If not, do I have to loop over all of the pointers and delete them as well, or is there an easier way to do it? My google-fu doesn't seem to give me any good answers to this question.
(And yeah, I know I need to use a vector. This is one of those "catch up on C++" type assignments in school.)
Yes you have to loop over the pointers, deleting individually.
Reason: What if other code had pointers to the objects in your array? The C++ compiler doesn't know if that's true or not, so you have to be explicit.
For an "easier way," two suggestions: (1) Make a subroutine for this purpose so at least you won't have to write the code more than once. (2) Use the "smart pointer" design paradigm where you hold an array of objects with reference-counters, then the objects are deleted when the objects are no longer referenced by any code.
I agree with Jason Cohen though we can be a bit clearer on the reason for needing to delete your pointers with the loop. For every "new" or dynamic memory allocation there needs to be a "delete" a memory de-allocation. Some times the "delete" can be hidden, as with smartpointers but it is still there.
int main()
{
int *pI = new int;
int *pArr = new int[10];
so far in the code we have allocated two chunks of dynamic memory. The first is just a general int the second is an array of ints.
delete pI;
delete [] pArr;
these delete statements clear the memory that was allocated by the "new"s
int ppArr = new int *[10];
for( int indx = 0; indx < 10; ++indx )
{
ppArr[indx] = new int;
}
This bit of code is doing both of the previous allocations. First we are creating space for our int in a dynamic array. We then need to loop through and allocate an int for each spot in the array.
for( int indx = 0; indx < 10; ++indx )
{
delete ppArr[indx];
}
delete [] ppArr;
Note the order that I allocated this memory and then that I de-allocated it in the reverse order. This is because if we were to do the delete [] ppArr; first we would lose the array that tells us what our other pointers are. That chunk or memory would be given back to the system and so can no longer be reliably read.
int a=0;
int b=1;
int c=2;
ppArr = new int *[3];
ppArr[0] = &a;
ppArr[1] = &b;
ppArr[2] = &c;
This I think should be mentioned as well. Just because you are working with pointers does not mean that the memory those pointers point to was dynamically allocated. That is to say just because you have a pointer doesn't mean it necessarily needs to be delete. The array I created here is dynamically allocated but the pointers point to local instances of ints When we delete this we only need to delete the array.
delete [] ppArr;
return 0;
}
In the end dynamically allocated memory can be tricky and anyway you can wrap it up safely like in a smart pointer or by using stl containers rather then your own can make your life much more pleasant.
See boost pointer container for a container that does the automatic deletion of contained pointers for you, while maintaining a syntax very close to ordinary STL containers.
Pointers are pretty much just memory references and not spiffy little self-cleaning .net objects. Creating proper destructors for each class will make the deletion a little cleaner than massive loops throughout the code.
Let's take a (pseudocoded) real world example .Imagine that you had a class like this:
class Street
{
public:
Street();
~Street();
private:
int HouseNumbers_[];
}
typedef *Street StreetSign;
If you have an array of street signs, and you delete your array of streetsigns, that doesn't mean that you automatically delete the sreets. They re still there, bricks and mortar, they just don't have those signs pointing to them any more. You have got rid of those specific instances of pointers to the streets.
An array of pointers is (conceptually) a bit like an array of integers, it's an array of numbers representing the memory locations of various objects. It isn't the objects themselves.
If you delete[] the array of pointers, all you have done is delete an array of integers.
I think you're going to have to loop over I'm afraid.
I don't know why this was answered so confusingly long.
If you delete the array of pointers, you will free
the memory used for an array of usually ints.
a pointer to an object is an integer containing the adress.
You deleted a bunch of adresses, but no objects.
delete does not care about the content of a memory space,
it calls a destructor(s) and marks the mem as free.
It does not care that it just deleted a bunch of adresses
of objects, it merely sees ints.
That's why you have to cycle through the array first! and call delete
on every element, then you can delete the storage of the array itself.
Well, now my answer got somewhat long... .... strange... ;)
Edit:
Jason's answer is not wrong, it just fails to hit the spot. Neither
the compiler nor anything else in c(++) cares about you deleting stuff that is elsewhere
pointed to. You can just do it. Other program parts trying to use the deleted objects
will segfault on you. But no one will hinder you.
Neither will it be a problem to destroy an array of pointers to objects, when the objects
are referenced elsewhere.