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.
Related
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().
In C++ do you always have to initialize a pointer to an object with the new keyword?
Or can you just have this too:
MyClass *myclass;
myclass->DoSomething();
I thought this was a pointer allocated on the stack instead of the heap, but since objects are normally heap-allocated, I think my theory is probably faulty?
Please advice.
No, you can have pointers to stack allocated objects:
MyClass *myclass;
MyClass c;
myclass = & c;
myclass->DoSomething();
This is of course common when using pointers as function parameters:
void f( MyClass * p ) {
p->DoSomething();
}
int main() {
MyClass c;
f( & c );
}
One way or another though, the pointer must always be initialised. Your code:
MyClass *myclass;
myclass->DoSomething();
leads to that dreaded condition, undefined behaviour.
No you can not do that, MyClass *myclass will define a pointer (memory for the pointer is allocated on stack) which is pointing at a random memory location. Trying to use this pointer will cause undefined behavior.
In C++, you can create objects either on stack or heap like this:
MyClass myClass;
myClass.DoSomething();
Above will allocate myClass on stack (the term is not there in the standard I think but I am using for clarity). The memory allocated for the object is automatically released when myClass variable goes out of scope.
Other way of allocating memory is to do a new . In that case, you have to take care of releasing the memory by doing delete yourself.
MyClass* p = new MyClass();
p->DoSomething();
delete p;
Remeber the delete part, else there will be memory leak.
I always prefer to use the stack allocated objects whenever possible as I don't have to be bothered about the memory management.
if you want the object on the stack, try this:
MyClass myclass;
myclass.DoSomething();
If you need a pointer to that object:
MyClass* myclassptr = &myclass;
myclassptr->DoSomething();
First I need to say that your code,
MyClass *myclass;
myclass->DoSomething();
will cause an undefined behavior.
Because the pointer "myclass" isn't pointing to any "MyClass" type objects.
Here I have three suggestions for you:-
option 1:- You can simply declare and use a MyClass type object on the stack as below.
MyClass myclass; //allocates memory for the object "myclass", on the stack.
myclass.DoSomething();
option 2:- By using the new operator.
MyClass *myclass = new MyClass();
Three things will hapen here.
i) Allocates memory for the "MyClass" type object on the heap.
ii) Allocates memory for the "MyClass" type pointer "myclass" on the stack.
iii) pointer "myclass" points to the memory address of "MyClass" type object on the heap
Now you can use the pointer to access member functions of the object after dereferencing the pointer by "->"
myclass->DoSomething();
But you should free the memory allocated to "MyClass" type object on the heap, before returning from the scope unless you want it to exists. Otherwise it will cause a memory leak!
delete myclass; // free the memory pointed by the pointer "myclass"
option 3:- you can also do as below.
MyClass myclass; // allocates memory for the "MyClass" type object on the stack.
MyClass *myclassPtr; // allocates memory for the "MyClass" type pointer on the stack.
myclassPtr = &myclass; // "myclassPtr" pointer points to the momory address of myclass object.
Now, pointer and object both are on the stack.
Now you can't return this pointer to the outside of the current scope because both allocated memory of the pointer and the object will be freed while stepping outside the scope.
So as a summary, option 1 and 3 will allocate an object on the stack while only the option 2 will do it on the heap.
if you want to access a method :
1) while using an object of a class:
Myclass myclass;
myclass.DoSomething();
2) while using a pointer to an object of a class:
Myclass *myclass=&abc;
myclass->DoSomething();
If you have defined a method inside your class as static, this is actually possible.
class myClass
{
public:
static void saySomething()
{
std::cout << "This is a static method!" << std::endl;
}
};
And from main, you declare a pointer and try to invoke the static method.
myClass * pmyClass;
pmyClass->saySomething();
/*
Output:
This is a static method!
*/
This works fine because static methods do not belong to a specific instance of the class and they are not allocated as a part of any instance of the class.
Read more on static methods here: http://en.wikipedia.org/wiki/Static_method#Static_methods
Simple solution for cast pointer to object
Online demo
class myClass
{
public:
void sayHello () {
cout << "Hello";
}
};
int main ()
{
myClass* myPointer;
myClass myObject = myClass(* myPointer); // Cast pointer to object
myObject.sayHello();
return 0;
}
I would like to define a class with a vector data member. The class looks as follows
class A{
...
private:
std::vector<int> v1;
...
};
If I use operator new to allocate memory for class A, the program is OK. However, if I get the memory from the pre-allocated memory and cast the pointer to type A*, the program will crash.
A* a = new A;
A* b = (A*)pre_allocated_memory_pointer.
I need one vector with variable size and hope to get the memory for A from one pre-allocated memory. Do you have any idea about the problem?
An std::vector is an object that requires initialization, you cannot just allocate memory and pretend you've got a vector.
If you need to control where to get the memory from the solution is defining operator::new for your class.
struct MyClass {
std::vector<int> x;
... other stuff ...
void *operator new(size_t sz) {
... get somewhere sz bytes and return a pointer to them ...
}
void operator delete(void *p) {
... the memory is now free ...
}
};
Another option is instead to specify where to allocate the object using placement new:
struct MyClass {
std::vector<int> x;
... other stuff ...
};
void foo() {
void * p = ... get enough memory for sizeof(MyClass) ...
MyClass *mcp = new (p) MyClass();
... later ...
mcp->~MyClass(); // Call destructor
... the memory now can be reused ...
}
Note however that std::vector manages itself the memory for the contained elements and therefore you'll need to use stl "allocators" if you want to control where the memory it needs is coming from.
It is not enough to cast the pre-allocated memory poiner to your user-defined type unless this UDT is "trivial".
Instead, you may want to use the placement new expression to actually call the constructor of your type at the provided region of memory:
A* b = new(pre_allocated_memory_pointer) A();
Of course, you need to ensure that your memory is properly aligned and can fit the whole object (i.e. its size is >= sizeof(A) ) beforehand.
Don't also forget to explicitly call the destructor for this object before de-allocating the underlying memory.
b.~A();
deallocate(pre_allocated_memory_pointer);
As I understand your question you are confusing the data memory of the std::vector with the memory it takes up as a member.
If you convert pre_allocated_memory_pointer to A*, then no constructor got called and you have an invalid object there. This means that the v1 member will not have been constructed and hence no memory has been allocated for the vector.
You could use placement new to construct the A instance at the pre_allocated_memory_pointer position but I doubt that is what you want.
In my opinion you want a custom allocator for the vector that gets the memory for the vector's data from the preallocated memory pool.
This is an allocation on the stack:
char inStack[10];
// and
MyStruct cl;
And this should be allocated in the heap:
char* inHeap = new char[10];
// and
MyClass cl = new MyClass();
What if MyClass contains a char test[10] variable? Does this:
MyClass cl = new MyClass()
...mean that the 10 byte long content of MyClass::test is allocated in the heap instead of the stack?
It would be allocated inside the object, so that if the object is on the heap, the array will be on the heap; if the object is on the stack, the array will be on the stack; if the object is in static memory in the executable, the array will be there also.
In C++, members of objects are part of the object itself. If you have the address of the object and it's size, you know that all the members of the class will be somewhere within the range [address, address + size), no matter where in memory that address actually is (heap, stack, etc).
If MyClass has a char test[10] member, it will be allocated the same way the instance of MyClass was allocated.
MyClass mc; //mc.test is on the stack
MyClass * mcp = new MyClass; //mcp->test is on the heap
The proper terms in the language are automatic and dynamic storage, and these make a bit more sense than stack and heap. In particular automatic storage does not imply stack in general, only in local variables in functions, but as you mention, if you are defining a member of a class, automatic storage will be wherever the enclosing object is, which can be the stack, the heap or a static object.
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").