Do I need to manage this array in any way or will the unique_ptr take care of it? I have read that if arry gets assigned a new value then it will no longer be managed. I am new to this don't understand it very well.
int main() {
int i = 0;
int maxSpaceSize = 10;
unique_ptr<int[]> arry (new int[maxSpaceSize]());
for (i = 0; i < maxSpaceSize; i++) {
arry[i] = i;
cout << arry[i];
cout << endl;
}
return 0;
}
My goal in this is to make and understand dynamic arrays with automatic garbage collection. At some point I would ask the user to define the size of the array and that would be assigned to maxSpaceSize.
Thanks for helpful input.
Do I need to manage this array in any way or will the unique_ptr take care of it?
The std::unique_ptr will take care. There's a specialization for raw array deleters to call delete [] pointee;
I have read that if arry gets assigned a new value then it will no longer be managed.
That's wrong information (emphasis mine).
The assignment operator overload of std::unique_ptr will delete the old pointee, and further take care of the new one.
So whenever you write something like
maxSpaceSize = 50;
arry = unique_ptr<int[]>(new int[maxSpaceSize]);
that behavior will apply.
See Live Demo
Related
Using Valgrind, I see that I have a problem while deleting the memory in the following function:
Obj1 Obj1::operator*(const Obj1& param) const {
int n = param.GetSize(2);
Obj2** s = new Obj2*[n];
for( int i = 0; i < n; ++i) {
s[i] = new Obj2(*this*param.GetColumn(i+1));
}
Obj1 res = foo(s,n);
for(int i=n-1;i>-1;i--) {
s[i]->~Obj2();
}
delete[] s;
return res;
Valgrind tells me that the leak comes from the line
s[i] = new Obj2(*this*param.GetColumn(i+1));
I'm not pretty sure if the problem is when I try to free the memory. Can anyone tell me how to fix this problem?
Here:
s[i] = new Obj2(*this*param.GetColumn(i+1));
you create a dynamic object and assign s[i]to point to it.
In order to delete it, you do this:
delete s[i];
Unless you do that, the allocation will leak.
You must repeat that in a loop for every i just like you repeated the allocations. You of course have to do this before you delete s itself.
s[i]->~Obj2();
Don't do that. Calling the destructor is not appropriate here. delete will call the destructor.
P.S. Don't use raw owning pointers. Use containers or smart pointers instead. std::vector is a standard containers for dynamic arrays.
P.P.S. You should avoid unnecessary dynamic allocation. Your example doesn't demonstrate any need to allocate the pointed objects dynamically. So, in this case you should probably use std::vector<Obj2>.
in Visual Studio 2010 i create a while statement in which i assign a pointer to pointer to a map.
Example:
std::map<int,std::tuple<int,std::string>** > dmap;
int i=0;
while (i<3){
std::tuple<int,std::string>* t = new std::tuple<int,std::string>(10+i,std::string("test"));
dmap[i] = &t;
dmap[i + 1 ] = &t;
i++;
}
.
.
.
for (auto it = d.begin();it!=d.end();++it)
{
if(*(it->second) != nullptr){
delete *(it->second);
*(it->second) = nullptr;
}
}
The problem is that the address of &t is always the same and so at the end the map always contains , for all keys that i entered, the last *t value.
What's the problem? (Resolved)
[Edit]
Now i modify the code beacause before it was incomplete, if i want to avoid to delete nullptr i need to have a pointer to pointer. Or not?
The problem is that you're putting a pointer to a local variable t into the map. After each loop, t is destroyed and the pointer is no longer valid.
I've no idea why you're using pointers at all, let alone pointers to pointers. You probably want to put the tuples themselves in the map:
std::map<int,std::tuple<int,std::string>> dmap;
for (int i = 0; i<3; ++i){
dmap[i] = {10+i, "test"};
}
i create a while statement in which i assign a pointer to pointer to a map
Sorry for saying this, but it sounds to me like you have bigger problems than the fact that t is the same (this looks like the xy problem).
Consider (in order) one of these alternatives:
store your tuples by value
store your tuples by single pointer (worse than "by value", better than "by pointer to pointer"). If you can do this, consider declaring your map over std::shared_ptr<std::tuple<...>>)
if you really need a map of pointers to pointers to tuples, consider creating a minimal proxy object that acts like a smart pointer to pointer internally (and manages the allocations for you in a safe manner) and like a regular type from the outside (and redeclare your map accordingly).
Either way, if you really need a map of pointers to pointers to tuples (for some reason), the allocation should be done like this:
std::map<int,std::tuple<int,std::string>**> dmap;
int i=0;
while (i<3) {
*dmap[ i ] = new std::tuple<int,std::string>{10 + i, "test"};
++i;
}
(The way you did it added the address of the same local (stack) variable to the map, which would lead to undefined behavior after you exit the local function).
Why are you interested in std::tuple<int,std::string>** ?
Wouldn't a std::tuple<int,std::string>* be sufficient ?
std::map<int,std::tuple<int,std::string>* > dmap;
int i=0;
while (i<3){
std::tuple<int,std::string>* t = new std::tuple<int,std::string>(10+i,std::string("test"));
dmap[i] = t;
i++;
}
Well, the address of t is always the same, because it is local variable that is stored on your stack. Each time you enter the block, t will be allocated on the same spot (as you're destroying t after you get out of your while body).
Instead, you need to allocate it on the heap (if this is really what you want to do).
std::tuple<int,std::string>** t = new std::tuple<int,std::string>*();
*t = new std::tuple<int,std::string>(10+i,std::string("test"));
dmap[i] = t;
I can't see what you're trying to accomplish, but this would be a better solution:
std::map<int,std::tuple<int,std::string>* > dmap;
int i=0;
while (i<3){
std::tuple<int,std::string>* t = new std::tuple<int,std::string>(10+i,std::string("test"));
dmap[i] = t;
i++;
}
Even better would be to use smart pointer instead raw one.
Even better would be to store objects by value (no pointers at all).
I have an array of pointers (that I created by calling new ptr*[size]). All of these pointers point to an object that was also put on the heap.
What is the proper way to delete the array and all new'd ptr's?
This is what I do now:
for (int i = 0; i < size; i++) delete array[i];
delete[] array; // Not sure since this double deletes array[0]
Does this do what I think it should?
Thanks
Every pointer allocated with new gets a corresponding delete. Every pointer allocated with new [] gets a corresponding delete []. That's really all you need to know. Of course, when you have a dynamically allocated array which contains dynamically allocated pointers the deallocation must occur in reverse order.
So it follows that the correct idiom would be...
int main()
{
int **container = new int*[n];
for(int i = 0; i < n; ++i)
container[i] = new int[size];
// ... and to deallocate...
for(int i = 0; i < n; ++i)
delete [] container[i];
delete [] container;
}
And then of course I say "stop doing that" and recommend you use a std::array or std::vector (and the template type would be unique_ptr<int>).
Yes, that does what you think it should. Since you did new for each element, you have to delete each element. And since you did new[] for the entire array, you need to delete[] the entire array.
As #djechlin rightly says in the comments, there's not really enough information to go on, but I'm presuming your prior code is something like this:
int** array = new int*[5];
for (int i = 0; i < 5; i++) {
array[i] = new int;
}
Note that array is not actually an array type. It is a "pointer to pointer to int" and the array of pointers it points to was allocated with new[]. That's why you need to delete[] it.
Yes. First you have to free the object each pointer in the array points to, then you have to free the array itself. In that order. If you reverse the order you'll have no reference to the objects and will leak a lot of memory.
Yes, first you delete each object to which elements of array point, and then you delete array of pointers itself. If you want to check your memory management, you can use tools like valgrind, they will be able to spot most errors.
I would like to know if there is a way to delete a pointer array without touching the pointed objects in memory.
I'm writing a restriction routine for a HashSet I implemented a couple of days ago, so when the hash table is full it gets replaced by another double sized table. I'm representing the hash table using an array of pointers to an object (User), and the array itself is declared dynamically in my HashSet class, so it can be deleted after copying all its content to the new table using a hash function.
So basically I need to:
Declare another table with a size that equals the double of the original array size.
Copy every pointer to User objects from my original array to the new one applying my hash function (it gets the User object from memory and it calculates the index using a string that represents the user's name).
After inserting all the pointers from the original array to the new one, I will have to free the allocated memory for the original array and replace the pointer in my HashSet class (member private userContainer) with the location of the new one (array).
The problem is that if I use delete[] userContainer to free the allocated memory for it, it will also delete every object in memory so the newly created replacement array will point to freed positions in memory!
What you describe does not sound right.
Let's say you have a class A and you create an array of As with:
A** array1 = new A*[32];
Then fill it:
for(int i = 0; i < 32; ++i)
array1[i] = new A();
Doing a delete[] array1 does not free the elements of array1.
So this is safe:
A** array1 = new A*[32];
for(int i = 0; i < 32; ++i)
array1[i] = new A();
A** arary2 = new A*[64];
for(i = 0; i < 32; ++i)
array2[i] = array1[i];
delete [] array1;
for(i = 0; i < 32; ++i)
// do something with array2[i]
In general, when you delete an array of pointers, whatever objects the pointers pointed to remain in existence. In fact, this is a potential source of large memory leaks.
But in some sort of reference-counted environment (eg, Objective-C or Qt), when you delete an array OBJECT (vs a simple [] array) then the reference counts are decremented and the objects will be deleted if the count goes to zero.
But if you're restructuring a hash table you'd better have somehow saved the pointer values before you delete the array, or else all the addressed objects will be lost. As you save them you can increment their reference counts (if you do it right).
(It would help to know what language you're dealing with, and what you mean by "array".)
I don't think your problem exists. Here's a baby example to show that there's nothing to worry about:
Foo * brr[10];
{
Foo * arr[10];
// This is not touching the objects!
for (Foo * it = arr; it != arr + 10; ++it) *it = new Foo;
std::copy(arr, arr + 10, brr);
} // no more arr
for (Foo * it = brr; it != brr + 10; ++it) delete *it; // fine
You can copy the pointers around freely as much as you like. Just remember to delete the object to which the pointers point when they're no longer needed.
A perhaps trivial reminder: Pointers don't have destructors; in particular, when a pointer goes out of scope, nothing happens.
Do you know the difference between malloc/free, new/delete and new[]/delete[]?
I figure that you might want to not use new[]/delete[] in your situation, as you don't want destructors to be called I guess?
In C++, Lets say I'm creating an array of pointers and each element should point to a data type MyType. I want to fill this array in a function fillArPtr(MyType *arPtr[]). Lets also say I can create MyType objects with a function createObject(int x). It works the following way:
MyType *arptr[10]; // Before there was a mistake, it was written: "int *arptr[10]"
void fillArPtr(MyType *arptr[])
{
for (int i = 0; i < 10; i++)
{
MyType myObject = createObject(i);
arptr[i] = new MyType(myobject);
}
}
Is it the best way to do it? In this program how should I use delete to delete objects created by "new" (or should I use delete at all?)
Since you asked "What is the best way", let me go out on a limb here and suggest a more C++-like alternative. Since your createObject is already returning objects by value, the following should work:
#include <vector>
std::vector<MyType> fillArray()
{
std::vector<MyType> res;
for (size_t i = 0; i != 10; ++i)
res.push_back(createObject(i));
return res;
}
Now you don't need to do any memory management at all, as allocation and clean-up is done by the vector class. Use it like this:
std::vector<MyType> myArr = fillArray();
someOtherFunction(myArr[2]); // etc.
someLegacyFunction(&myArr[4]); // suppose it's "void someLegacyFunction(MyType*)"
Do say if you have a genuine requirement for manual memory management and for pointers, though, but preferably with a usage example.
Your method places the array of pointers on the stack, which is fine. Just thought I'd point out that it's also possible to store your array of pointers on the heap like so. Youd do this if you want your array to persist beyond the current scope
MyType **arptr = new MyType[10];
void fillArPtr(MyType *arptr[])
{
for (int i = 0; i < 10; i++)
{
MyType myObject = createObject(i);
arptr[i] = new MyType(myobject);
}
}
If you do this, don't forget to delete the array itself from the heap
for ( int i = 0 ; i < 10 ; i++ ) {
delete arptr[i];
}
delete [] arptr;
If you're going to use vector, and you know the size of the array beforehand, you should pre-size the array. You'll get much better performance.
vector<MyType*> arr(10);
for (int i = 0; i < 10; i++)
{
delete arptr[i];
arptr[i] = 0;
}
I suggest you look into boost shared_ptr (also in TR1 library)
Much better already:
std::vector<MyType*> vec;
for (int i=0; i<10; i++)
vec.push_back(new MyType(createObject(i));
// do stuff
// cleanup:
while (!vec.empty())
{
delete (vec.back());
vec.pop_back();
}
Shooting for the stars:
typedef boost::shared_ptr<MyType> ptr_t;
std::vector<ptr_t> vec;
for (int i=0; i<10; i++)
vec.push_back(ptr_t(new MyType(createObject(i)));
You would basically go through each element of the array and call delete on it, then set the element to 0 or null.
for (int i = 0; i < 10; i++)
{
delete arptr[i];
arptr[i] = 0;
}
Another way to do this is with an std::vector.
Use an array of auto_ptrs if you don't have to return the array anywhere. As long as you don't make copies of the auto_ptrs, they won't change ownership and they will deallocate their resources upon exiting of the function since its RAII based. It's also part of the standard already, so don't need boost to use it :) They're not useful in most places but this sounds like a good one.
You can delete the allocated objects using delete objPtr. In your case,
for (int i = 0; i < 10; i++)
{
delete arptr[i];
arptr[i] = 0;
}
The rule of thumb to remember is, if you allocate an object using new, you should delete it. If you allocate an array of objects using new[N], then you must delete[] it.
Instead of sticking pointers into a raw array, have a look at std::array or std::vector. If you also use a smart pointer, like std::unique_ptr to hold the objects within an std::array you don't need to worry about deleting them.
typedef std::array<std::unique_ptr<MyType>, 10> MyTypeArray;
MyTypeArray arptr;
for( MyTypeArray::iterator it = arptr.begin(), int i = 0; it != arptr.end(); ++it ) {
it->reset( new MyType( createObject(i++) ) );
}
You don't need to worry about deleting those when you're done using them.
Is the createObject(int x) function using new to create objects and returning a pointer to this?. In that case, you need to delete that as well because in this statement
new MyType( createObject(i++) )
you're making a copy of the object returned by createObject, but the original is then leaked. If you change createObject also to return an std::unique_ptr<MyType> instead of a raw pointer, you can prevent the leak.
If createObject is creating objects on the stack and returning them by value, the above should work correctly.
If createObject is not using new to create objects, but is creating them on the stack and returning pointers to these, your program is not going to work as you want it to, because the stack object will be destroyed when createObject exits.