Is it possible and good practise to initialize a member pointer with a dynamically allocated pointer? Should I delete the pointer in the destructor?
class Apple
{
public:
Apple(int* counter) : counter_(counter);
~Apple(); // should I delete counter_ here?
private:
int* counter_;
}
int main()
{
someptr = new int;
apple_fruit = Apple(someptr);
delete someptr;
return 0;
}
I am fairly new to C++ and still have some confusion on how best to deal with dynamically allocated memory especially when its used for initialization.
Yes, it's possible to initialize a member pointer with a pointer to dynamically allocated data. I've seen this done in instances where a class needs access to an instance of another (dynamically allocated) class.
It's good practice only if you absolutely need to do it. If it's simply an integer we're dealing with (as in your example) then don't use a pointer and store the actual integer instead.
For deletion, do not delete the pointer in the class destructor unless it's your class that originally allocated the data. Your instinct was correct to delete it in main() because it was created in main().
Related
Given the following code:
class MyClass
{
public:
char array[10];
};
int main()
{
MyClass *p = new MyClass;
...
}
As far as I understand - new allocates the object on the heap.
But also, the array is allocated on the stack (no new operator).
So, is the array allocated on heap (because the object is at the heap) or on the program stack?
But also, the array is allocated on the stack (no new operator)
No, the array is a member of the object. It's a part of it. If the object is dynamically allocated, then all of its parts are too.
Note I said all of its parts. We can tweak your example:
class MyClass
{
public:
char *p_array;
};
int main()
{
char array[10];
MyClass *p = new MyClass{array};
// Other code
}
Now the object contains a pointer. The pointer, being a member of the object, is dynamically allocated. But the address it holds, is to an object with automatic storage duration (the array).
Now, however, the array is no longer part of the object. That disassociation is what makes the layout you had in mind possible.
What MyClass *p = new MyClass; really means is that you want to allocate sizeof(MyClass) bytes on the heap/free store to store every member of MyClass. The size of a class is based on it's members. array is a member of MyClass and thus because MyClass is allocated on the free store, so is array.
My following question is on memory management. I have for example an int variable not allocated dynamically in a class, let's say invar1. And I'm passing the memory address of this int to another classes constructor. That class does this:
class ex1{
ex1(int* p_intvar1)
{
ptoint = p_intvar1;
}
int* ptoint;
};
Should I delete ptoint? Because it has the address of an undynamically allocated int, I thought I don't need to delete it.
And again I declare an object to a class with new operator:
objtoclass = new ex1();
And I pass this to another class:
class ex2{
ex2(ex1* p_obj)
{
obj = p_obj;
}
ex1* obj;
};
Should I delete obj when I'm already deleting objtoclass?
Thanks!
Because it has the address of an undynamically allocated int I thought I don't need to delete it.
Correct.
Should I delete obj when I'm already deleting objtoclass?
No.
Recall that you're not actually deleting pointers; you're using pointers to delete the thing they point to. As such, if you wrote both delete obj and delete objtoclass, because both pointers point to the same object, you'd be deleting that object twice.
I would caution you that this is a very easy mistake to make with your ex2 class, in which the ownership semantics of that pointed-to object are not entirely clear. You might consider using a smart pointer implementation to remove risk.
just an appendix to the other answers
You can get rid of raw pointers and forget about memory management with the help of smart pointers (shared_ptr, unique_ptr).
The smart pointer is responsible for releasing the memory when it goes out of scope.
Here is an example:
#include <iostream>
#include <memory>
class ex1{
public:
ex1(std::shared_ptr<int> p_intvar1)
{
ptoint = p_intvar1;
std::cout << __func__ << std::endl;
}
~ex1()
{
std::cout << __func__ << std::endl;
}
private:
std::shared_ptr<int> ptoint;
};
int main()
{
std::shared_ptr<int> pi(new int(42));
std::shared_ptr<ex1> objtoclass(new ex1(pi));
/*
* when the main function returns, these smart pointers will go
* go out of scope and delete the dynamically allocated memory
*/
return 0;
}
Output:
ex1
~ex1
Should I delete obj when I'm already deleting objtoclass?
Well you could but mind that deleting the same object twice is undefined behaviour and should be avoided. This can happen for example if you have two pointers for example pointing at same object, and you delete the original object using one pointer - then you should not delete that memory using another pointer also. In your situation you might as well end up with two pointers pointing to the same object.
In general, to build a class which manages memory internally (like you do seemingly), isn't trivial and you have to account for things like rule of three, etc.
Regarding that one should delete dynamically allocated memory you are right. You should not delete memory if it was not allocated dynamically.
PS. In order to avoid complications like above you can use smart pointers.
You don't currently delete this int, or show where it's allocated. If neither object is supposed to own its parameter, I'd write
struct ex1 {
ex1(int &i_) : i(i_) {}
int &i; // reference implies no ownership
};
struct ex2 {
ex2(ex1 &e_) : e(e_) {}
ex1 &e; // reference implies no ownership
};
int i = 42;
ex1 a(i);
ex2 b(a);
If either argument is supposed to be owned by the new object, pass it as a unique_ptr. If either argument is supposed to be shared, use shared_ptr. I'd generally prefer any of these (reference or smart pointer) to raw pointers, because they give more information about your intentions.
In general, to make these decisions,
Should I delete ptoint?
is the wrong question. First consider things at a slightly higher level:
what does this int represent in your program?
who, if anyone, owns it?
how long is it supposed to live, compared to these classes that use it?
and then see how the answer falls out naturally for these examples:
this int is an I/O mapped control register.
In this case it wasn't created with new (it exists outside your whole program), and therefore you certainly shouldn't delete it. It should probably also be marked volatile, but that doesn't affect lifetime.
Maybe something outside your class mapped the address and should also unmap it, which is loosely analogous to (de)allocating it, or maybe it's simply a well-known address.
this int is a global logging level.
In this case it presumably has either static lifetime, in which case no-one owns it, it was not explicitly allocated and therefore should not be explicitly de-allocated
or, it's owned by a logger object/singleton/mock/whatever, and that object is responsible for deallocating it if necessary
this int is being explicitly given to your object to own
In this case, it's good practice to make that obvious, eg.
ex1::ex1(std::unique_ptr<int> &&p) : m_p(std::move(p)) {}
Note that making your local data member a unique_ptr or similar, also takes care of the lifetime automatically with no effort on your part.
this int is being given to your object to use, but other objects may also be using it, and it isn't obvious which order they will finish in.
Use a shared_ptr<int> instead of unique_ptr to describe this relationship. Again, the smart pointer will manage the lifetime for you.
In general, if you can encode the ownership and lifetime information in the type, you don't need to remember where to manually allocate and deallocate things. This is much clearer and safer.
If you can't encode that information in the type, you can at least be clear about your intentions: the fact that you ask about deallocation without mentioning lifetime or ownership, suggests you're working at the wrong level of abstraction.
Because it has the address of an undynamically allocated int, I
thought I don't need to delete it.
That is correct. Simply do not delete it.
The second part of your question was about dynamically allocated memory. Here you have to think a little more and make some decisions.
Lets say that your class called ex1 receives a raw pointer in its constructor for a memory that was dynamically allocated outside the class.
You, as the designer of the class, have to decide if this constructor "takes the ownership" of this pointer or not. If it does, then ex1 is responsible for deleting its memory and you should do it probably on the class destructor:
class ex1 {
public:
/**
* Warning: This constructor takes the ownership of p_intvar1,
* which means you must not delete it somewhere else.
*/
ex1(int* p_intvar1)
{
ptoint = p_intvar1;
}
~ex1()
{
delete ptoint;
}
int* ptoint;
};
However, this is generally a bad design decision. You have to root for the user of this class read the commentary on the constructor and remember to not delete the memory allocated somewhere outside class ex1.
A method (or a constructor) that receives a pointer and takes its ownership is called "sink".
Someone would use this class like:
int* myInteger = new int(1);
ex1 obj(myInteger); // sink: obj takes the ownership of myInteger
// never delete myInteger outside ex1
Another approach is to say your class ex1 does not take the ownership, and whoever allocates memory for that pointer is the responsible for deleting it. Class ex1 must not delete anything on its destructor, and it should be used like this:
int* myInteger = new int(1);
ex1 obj(myInteger);
// use obj here
delete myInteger; // remeber to delete myInteger
Again, the user of your class must read some documentation in order to know that he is the responsible for deleting the stuff.
You have to choose between these two design decisions if you do not use modern C++.
In modern C++ (C++ 11 and 14) you can make things explicit in the code (i.e., do not have to rely only on code documentation).
First, in modern C++ you avoid using raw pointers. You have to choose between two kinds of "smart pointers": unique_ptr or shared_ptr. The difference between them is about ownership.
As their names say, an unique pointer is owned by only one guy, while a shared pointer can be owned by one or more (the ownership is shared).
An unique pointer (std::unique_ptr) cannot be copied, only "moved" from one place to another. If a class has an unique pointer as attribute, it is explicit that this class has the ownership of that pointer. If a method receives an unique pointer as copy, it is explicit that it is a "sink" method (takes the ownership of the pointer).
Your class ex1 could be written like this:
class ex1 {
public:
ex1(std::unique_ptr<int> p_intvar1)
{
ptoint = std::move(p_intvar1);
}
std::unique_ptr<int> ptoint;
};
The user of this class should use it like:
auto myInteger = std::make_unique<int>(1);
ex1 obj(std::move(myInteger)); // sink
// here, myInteger is nullptr (it was moved to ex1 constructor)
If you forget to do "std::move" in the code above, the compiler will generate an error telling you that unique_ptr is not copyable.
Also note that you never have to delete memory explicitly. Smart pointers handle that for you.
My concern is whether or not the array should be deallocated. Here is an example:
typedef struct
{
int *values;
int length;
} a_struct;
void foo()
{
a_struct myStruct;
myStruct.values = new int[NUM];
delete[] myStruct.values; // Is this needed?
return;
}
My understanding is that myStruct (which is on the stack) will get deleted automatically upon the "return" statement. Does it delete "values" as well?
It does deallocate the pointer values, but not what it points to - after all, what does a_struct know about what you assigned to that pointer? Maybe it's a pointer to stuff allocated on the stack, or to an array shared with another struct.
So, yes, you need to manually deallocate it (although in modern C++ often "smart pointers" are used to manage memory).
No, it doesn't, you should delete it manually. myStruct going out of scope (and thus the myStruct.values member, i. e. the pointer being invalidated) has nothing to do with the dynamically allocated memory. The golden rule: if you call new[], always delete[] (same for new and delete).
Yes it is needed, the struct only stores the address of the array.
These days people would just store a std::vector<> (or if you just want an owning pointer to something a std::unique_ptr<>).
Nothing gets 'deleted'. The stack is popped. Period. As the struct doesn't have a destructor, nothing else happens.
I'd like to know how C++ is dealing with memory of "objects" created by pointer inside class methods or functions.
For example method of class Example
void Example::methodExample()
{
ExampleObject *pointer = new ExampleObject("image.jpg");
}
Should i somehow delete this or it's automatically removed?
Sorry if my question is stupid but i am beginner : P
You have two options.
If you use a raw pointer, as you are using in your example, you must manually delete objects that were created with new.
If you don't, you have created a memory leak.
void Example::methodExample()
{
ExampleObject *pointer = new ExampleObject("image.jpg");
// Stuff
delete pointer;
}
Or you may use smart pointers, such as boost::scoped_ptr or C++11's std::unique_ptr.
These objects will automatically delete their pointed-to contents when they are deleted.
Some (like me) will say that this approach is preferred, because your ExampleObject will be correctly deleted even if an exception is thrown and the end of the function isn't reached.
void Example::methodExample()
{
boost::scoped_ptr<ExampleObject> pointer( new ExampleObject("image.jpg") );
// Stuff
}
You shouldn't be doing your own memory management at all in modern C++. Use unique_ptr or scoped_ptr, which will automatically delete the pointer when they go out of scope.
I think the appriate approach for dealing with raw pointers (as you exemplified) is to store the pointer as a member of the class. Then you can allocate memory for this pointer in any method you would like and leave to free the memory on the destructor of the class. Something along these lines:
class Example
{
public:
Example();
~Example();
void methodExample();
private:
ExampleObject* pointer;
};
void Example::Example()
: pointer(NULL)
{
}
void Example::~Example()
{
if (pointer) // release memory only if it was allocated
delete pointer;
}
void Example::methodExample()
{
pointer = new ExampleObject("image.jpg");
// add a safety check to verify if the allocation was successful
}
If your object is scoped within the function then your correct construct is not to use a pointer at all but use an automatic object, which should be created like this.
ExampleObject example("image.jpg");
You might use a pointer where you are, for example, in an if construct at the time, where the else condition would not construct an object, and then you want to use the object later.
In such a case use an automatic pointer object, preferably unique_ptr if available, boost::scoped_ptr if not, but even the deprecated std::auto_ptr is better than a raw one. For example:
std::unique_ptr<ExampleObject> example;
if( usingAnExample )
{
example.reset( new ExampleObject("image.jpg") );
}
else
{
// do stuff
}
// I still need example here if it was created
You should
delete pointer;
when you no longer need it. The pointer goes out of scope at the end of the function but the memory is still allocated on the heap.
I'm a bit confused about handling an array of objects in C++, as I can't seem to find information about how they are passed around (reference or value) and how they are stored in an array.
I would expect an array of objects to be an array of pointers to that object type, but I haven't found this written anywhere. Would they be pointers, or would the objects themselves be laid out in memory in an array?
In the example below, a custom class myClass holds a string (would this make it of variable size, or does the string object hold a pointer to a string and therefore take up a consistent amount of space. I try to create a dynamic array of myClass objects within a myContainer. In the myContainer.addObject() method I attempt to make a bigger array, copy all the objects into it along with a new object, then delete the old one. I'm not at all confident that I'm cleaning up my memory properly with my destructors - what improvements could I make in this area?
class myClass
{
private:
string myName;
unsigned short myAmount;
public:
myClass(string name, unsigned short amount)
{
myName = name;
myAmount = amount;
}
//Do I need a destructor here? I don't think so because I don't do any
// dynamic memory allocation within this class
};
class myContainer
{
int numObjects;
myClass * myObjects;
public:
myContainer()
{
numObjects = 0;
}
~myContainer()
{
//Is this sufficient?
//Or do I need to iterate through myObjects and delete each
// individually?
delete [] myObjects;
}
void addObject(string name, unsigned short amount)
{
myClass newObject = new myClass(name, amount);
myClass * tempObjects;
tempObjects = new myClass[numObjects+1];
for (int i=0; i<numObjects; i++)
tempObjects[i] = myObjects[i]);
tempObjects[numObjects] = newObject;
numObjects++;
delete newObject;
//Will this delete all my objects? I think it won't.
//I'm just trying to delete the old array, and have the new array hold
// all the objects plus the new object.
delete [] myObjects;
myObjects = tempObjects;
}
};
An array in C++ is an array of objects laid out in memory.
So for example in:
struct pair {
int x; int y;
};
...
pair array[10];
Each item in the array is going to be with a size of two ints.
If you want an array of pointers you can simply declare one:
pair* array_of_pointers[10];
The string objects have pointers to the variable size part of the string. So they're safe.
In fact they're the important lesson here. Same way you use the string class to avoid excessive memory handling you can use the vector class to avoid all the troubles of handling a dynamic array.
For the case you're doing this as an exercise. Here are a few problems:
newObject needs to be allocated locally, without new. This will make the code correct (as newObject is not a pointer and new returns a pointer) and will also save you the trouble of explicitly handling memory. (On a more advanced note, this makes the code exception safe in one more location)
myObject is never initialized. And you don't use initialization lists in the constructor. The constructor should look like this:
myContainer() : numObjects(0), myObjects(NULL)
{
}
The destructors in the code are exactly as they should be.
No, a dynamic array is not an array of pointers to that type - its a pointer to the first element. The elements are laid out consecutively in memory and are destroyed when the array is delete[]ed.
Thus your deallocation looks fine - you create dynamic arrays of myClass objects so you don't have to delete them individually. You would only have to do this if you had an array of pointers to (dynamically allocated) objects.
There are two definitive errors though:
tempObjects[numObjects] = newObject; // assign a myClass pointer to a myClass instance?
This should be e.g.:
tempObjects[numObjects] = myClass(name, amount);
Also, myObjects is never initialized, which means it contains garbage and dereferencing/using it leads to undefined behaviour.
Finally, unless you are doing this for learning purposes, simply use containers like std::vector that do all the work for you already.
I would expect an array of objects to be an array of pointers to that object type, but I haven't found this written anywhere. Would they be pointers, or would the objects themselves be laid out in memory in an array?
The array will consist of the objects themselves. If you want to have an array of pointer you will have to declare that:
myClass ** tempObjects;
tempObjects = new myClass*[numObjects+1];
I assume you are used to C# or Java? In those languages objects can only be allocated on heap and are always accessed by referenced. It is possible in C++, but in C++ you can also put objects directly on the stack, or directly construct an array of the objects themselves.
In the example below, a custom class myClass holds a string (would this make it of variable size, or does the string object hold a pointer to a string and therefore take up a consistent amount of space?
Number two: The string object itself is constant in size, but has a pointer to a dynamically sized buffer allocated from the heap.
I think the deallocation looks fine. The code could be written more efficient in various ways, but it looks correct.
Try to test it, to see what happens (yes, that may be compiler-specific, but still)...
You could try to add a custom destructor to myClass (even though you don't need one), that increments a "global" counter when called, Then print the counter after deleting the array.
I would expect the destructor of each object to be called. Note that quite often objects are stored "by-pointers" to allow for inherited objects to be put into the array (avoiding "slicing").