This is a very newbie question, but something completely new to me. In my code, and everywhere I have seen it before, new objects are created as such...
MyClass x = new MyClass(factory);
However, I just saw some example code that looks like this...
MyClass x(factory);
Does that do the same thing?
Not at all.
The first example uses dynamic memory allocation, i.e., you are allocating an instance of MyClass on the heap (as opposed to the stack). You would need to call delete on that pointer manually or you end up with a memory leak. Also, operator new returns a pointer, not the object itself, so your code would not compile. It needs to change to:
MyClass* x = new MyClass(factory);
The second example allocated an instance of MyClass on the stack. This is very useful for short lived objects as they will automatically be cleaned up when the leave the current scope (and it is fast; cleaning up the stack involves nothing more than incrementing or decrementing a pointer).
This is also how you would implement the Resource Acquisition is Initialization pattern, more commonly referred to as RAII. The destructor for your type would clean up any dynamically allocated memory, so when the stack allocated variable goes out of scope any dynamically allocated memory is cleaned up for you without the need for any outside calls to delete.
No. When you use new, you create objects off the heap that you must then delete later. In addition, you really need MyClass*. The other form creates an object on the stack that will be automatically destroyed at end of scope.
Related
I am new to c++ but from what I understood you need to delete objects from memory when you are done with them.
Having a class called myClass. If I create a new instance and call some of its functionalities. Like so:
MyClass p;
p.funcCall(12);
p.anOtherFuncCall(4);
How am I supposed to free the memory occupied by p again? I read this Microsoft article. But if I change it to:
MyClass* p = new MyClass
... call fucntions
delete p;
I can no longer call my functions like p.funcCall(12).
If I understood memory management in c++ incorrectly I would love to hear that as well.
In this code
MyClass p;
p.funcCall(12);
p.anOtherFuncCall(4);
You don't have to manually delete p. It is automatically invalidated once it goes out of scope. This is explained in greater detail here. You can just leave it this way.
MyClass* p = new MyClass
... call fucntions
delete p;
You can also do it that way if you want. Since p is not a MyClass anymore but a pointer to one, the syntax is different, though. You have to write it like this instead:
p->funcCall(12);
So basically C++ won't manage memory for you, at least it's not a default feature of the language. That certainly doesn't mean that you need to store every object as a pointer and free it manually though. In your case the object is initialized in the local scope which means it will get destroyed as soon as it leaves that scope. This is because you constructed it as a value, if you had allocated memory yourself for it (i.e global scope) then you're responsible for freeing said memory. There's another option for pointers as well though, using smart pointers will automate the cleanup of objects in the global scope.
I have an object with a vector of pointers to other objects in it, something like this:
class Object {
...
vector<Object*> objlist;
...
};
Now, Objects will be added to list in both of these ways:
Object obj;
obj.objlist.push_back(new Object);
and
Object name;
Object* anon = &name;
obj.objlist.push_back(anon);
If a make a destructor that is simply
~Object {
for (int i = 0; i < objlist.size(); i++) {
delete objlist[i];
objlist[i] = NULL;
}
}
Will there be any adverse consequences in terms of when it tries to delete an object that was not created with new?
Yes, there will be adverse effects.
You must not delete an object that was not allocated with new. If the object was allocated on the stack, your compiler has already generated a call to its destructor at the end of its scope. This means you will call the destructor twice, with potentially very bad effects.
Besides calling the destructor twice, you will also attempt to deallocate a memory block that was never allocated. The new operator presumably puts the objects on the heap; delete expects to find the object in the same region the new operator puts them. However, your object that was not allocated with new lives on the stack. This will very probably crash your program (if it does not already crash after calling the destructor a second time).
You'll also get in deep trouble if your Object on the heap lives longer than your Object on the stack: you'll get a dangling reference to somewhere on the stack, and you'll get incorrect results/crash the next time you access it.
The general rule I see is that stuff that live on the stack can reference stuff that lives on the heap, but stuff on the heap should not reference stuff on the stack because of the very high chances that they'll outlive stack objects. And pointers to both should not be mixed together.
No, you can only delete what you newed
Object* anon = &name;
When name goes out of scope, you will have an invalid pointer in your vector.
What you're actually asking is whether it's safe to delete an object not allocated via new through the delete operator, and if so, why?
Unfortunately, this is obfuscated by some other problems in your code. As mentioned, when name goes out of scope, you're going to end up with an invalid pointer.
See zneak's answer for why your original question doesn't result in a safe operation, and why the scope for name actually matters.
This will not work - if you delete an object that wasn't allocated by new you've violated the rules or the delete operator.
If you need to have your vector store objects that may or may not need to be deleted, you'll need to keep track of that somehow. One option is to use a smart pointer that keeps track of whether the pointed to object is dynamic or not. For example, shared_ptr<> allows you to specify a deallocator object when constructing the shard_ptr<> and as the docs mention:
For example, a "no-op" deallocator is useful when returning a shared_ptr to a statically allocated object
However, you should still be careful when passing pointers to automatic variables - if the vector's lifetime is longer than the lifetime of the variable then it'll be refering to garbage at some point.
I have an object with a vector of pointers to other objects in it, something like this:
class Object {
...
vector<Object*> objlist;
...
};
Now, Objects will be added to list in both of these ways:
Object obj;
obj.objlist.push_back(new Object);
and
Object name;
Object* anon = &name;
obj.objlist.push_back(anon);
If a make a destructor that is simply
~Object {
for (int i = 0; i < objlist.size(); i++) {
delete objlist[i];
objlist[i] = NULL;
}
}
Will there be any adverse consequences in terms of when it tries to delete an object that was not created with new?
Yes, there will be adverse effects.
You must not delete an object that was not allocated with new. If the object was allocated on the stack, your compiler has already generated a call to its destructor at the end of its scope. This means you will call the destructor twice, with potentially very bad effects.
Besides calling the destructor twice, you will also attempt to deallocate a memory block that was never allocated. The new operator presumably puts the objects on the heap; delete expects to find the object in the same region the new operator puts them. However, your object that was not allocated with new lives on the stack. This will very probably crash your program (if it does not already crash after calling the destructor a second time).
You'll also get in deep trouble if your Object on the heap lives longer than your Object on the stack: you'll get a dangling reference to somewhere on the stack, and you'll get incorrect results/crash the next time you access it.
The general rule I see is that stuff that live on the stack can reference stuff that lives on the heap, but stuff on the heap should not reference stuff on the stack because of the very high chances that they'll outlive stack objects. And pointers to both should not be mixed together.
No, you can only delete what you newed
Object* anon = &name;
When name goes out of scope, you will have an invalid pointer in your vector.
What you're actually asking is whether it's safe to delete an object not allocated via new through the delete operator, and if so, why?
Unfortunately, this is obfuscated by some other problems in your code. As mentioned, when name goes out of scope, you're going to end up with an invalid pointer.
See zneak's answer for why your original question doesn't result in a safe operation, and why the scope for name actually matters.
This will not work - if you delete an object that wasn't allocated by new you've violated the rules or the delete operator.
If you need to have your vector store objects that may or may not need to be deleted, you'll need to keep track of that somehow. One option is to use a smart pointer that keeps track of whether the pointed to object is dynamic or not. For example, shared_ptr<> allows you to specify a deallocator object when constructing the shard_ptr<> and as the docs mention:
For example, a "no-op" deallocator is useful when returning a shared_ptr to a statically allocated object
However, you should still be careful when passing pointers to automatic variables - if the vector's lifetime is longer than the lifetime of the variable then it'll be refering to garbage at some point.
Suppose I have a class named A:
Class A
{
...
}
And what's the difference between the following 2 approaches to instanciate an object:
void main(void)
{
A a; // 1
A *pa=new A(); // 2
}
As my current understanding (not sure about this yet):
Approach 1 allocate the object a on the stack frame of the main() method, and so this object cannot deleted because that deletion doesn't make sense (don't know why yet, could someone explain that?).
Approach 2 allocate the object a on the heap of the process and also a A* vairable pa on the stack frame of the main() method, so the object can be deleted and and the pa can be assigned null after the deletion.
Am I right? If my understanding is correct, could someone tell me why i cannot delete the a object from the stack in approach 1?
Many thanks...
Object a has automatic storage duration so it will be deleted automatically at the end of the scope in which it is defined. It doesn't make sense to attempt to delete it manually. Manually deletion is only required for objects with dynamic storage duration such as *pa which has been allocated using new.
The objects live time is limited to
the scope the variable is defined
in, once you leave the scope the
object will be cleaned up. In c++ a
scope is defined by any Block
between { an the corresponding }.
Here only the pointer is on the stack and not the object, so when
you leave the scope only the pointer
will be cleaned up, the object will
still be around somewhere.
To the part of deleting an object, delete not only calls the destructor of your object but also releases its memory, this would not work as the memory management of the stack is automated by the compiler, in contrast the heap is not automated and requires calls to new and delete to manage the live time of an object.
Any object created by a call to new has to be deleted once, forgetting to do this results in an memory leak as the objects memory will never be released.
Approach 1 declared a variable and created an object. In Approach 2, you created an instance and pointer to it.
EDIT : In approach 1, the object will go out of scope and will be automatically deleted. In approach 2, the pointer will be automatically deleted, but not what it is pointing to. That will be your job.
Imagine stack as void* stack = malloc(1.000.000);
Now, this memory block is managed internally by the compiler and the CPU.
It is a shared piece of memory. Every function can use it to store temporary objects there.
That's called automatic storage. You cannot delete parts of that memory because its purpose is
to be used again again. If you explicitly delete memory, that memory returns back to the system,
and you don't want that to happen in a shared memory.
In a way, automatic objects are also get deleted. When an object gets out of scope the compiler places
an invisible call to object's destructor and the memory is available again.
You cannot delete objects on the stack because it's implemented in memory exactly that way -- as a stack. As you create objects on the stack, they are added on top of each other. As the objects leave scope, they are destroyed from the top, in the opposite order they were created in (add to the top of the stack, and remove from the top of the stack). Trying to call delete on something in the stack would break that order. The analogy would be like trying to pull some paper out of the middle of a stack of papers.
The compiler controls how objects are created and removed on the stack. It can do this because it knows exactly how large each object on the stack is. Since the stack size is set at compile time, it means that allocating memory for things on the stack is extremely fast, much faster than allocating memory from the heap, which is controlled by the operating system.
Allocation does two things:
1) Allocates memory for the object
2) Calls the constructor on the allocated memory
Deletion does two things:
1) Calls the destructor on the object
2) Deallocates the memory used by the destructed object
When you allocate on the stack (A a;), you're telling the compiler "please make an object for me, by allocating memory, then call the constructor on that memory. And while you're at it, could you handle calling the destructor and freeing the memory, when it goes out of scope? Thanks!". Once the function (main) ends, the object goes out of scope, the destructor is called, and the memory is freed.
When you allocate on the heap (A* pa = new A();), you're telling the compiler "please make an object for me. I know what I'm doing, so don't bother calling the destructor or freeing the memory. I'll tell you when to do it, some other time". Once the function (main) ends, the object you allocated stays in scope, and is not destructed or freed. Hopefully you have a pointer to it stored somewhere else in your program (as in, you copied pa to some other variable with a bigger scope). You're gonna have to tell the compiler to destruct the object and free the memory at some point in the future. Otherwise, you get a memory leak.
Simply put, the "delete" command is only for objects allocated on the heap, because that's the manual memory management interface in C++ - new/delete. It is a command for the heap allocator, and the heap allocator doesn't know anything about stack allocated objects. If you try to call delete on a stack allocated object, you might as well have called it on a random memory address - they're the same thing as far as the heap allocator is concerned. Very much like trying to access an object outside array bounds:
int a[10];
std::cout << a[37] << "\n"; // a[37] points at... ? no one knows!
It just isn't meant to do that :)
Edit:
P.S. Memory leaks are more important when you are allocating memory in a function other than main. When the program ends, leaked memory gets deallocated, so a memory leak in main might not be a big deal, depending on your scenario. However, destructors never get called on leaked objects. If the destructor does something important, like closing a database or a file, then you might have a more serious bug on your hands.
stack memory is not being managed on the same way as heap memory.
there is no point to delete objects from stack: they will be deleted
automatically upon end of scope/function.
I'm a C and Java programmer, so memory allocation and OOP aren't anything new to me. But, I'm not sure about how exactly to avoid memory leaks with C++ implementation of objects. Namely:
string s1("0123456789");
string s2 = s1.substr(0,3);
s2 now has a new string object, so it must be freed via:
delete &s2;
Right?
Moreover, am I correct to assume that I'll have to delete the address for any (new) object returned by a function, regardless of the return type not being a pointer or reference? It just seems weird that an object living on the heap wouldn't be returned as a pointer when it must be freed.
No.
You only need to free memory you allocate (i.e. via new or memalloc).
No,
Both s1 and s2 will get destructed when out of scope.
s1.substr() will create a temporary object that you don't have to think of.
There are a couple of layers to the answers.
First, variables can be declared in several different ways:
As local variables (either inside a function or as class members). Examples: int i, or int i = 42. These have automatic storage duration (these examples are technically shorthand for auto int i, or auto int i = 42, although the auto keyword is virtually never used. What this means is that these variables will be automatically freed when they go out of scope. Their destructor is guaranteed to be called (no matter how you leave the scope, whether it is by a function return or by throwing an exception, their destructor will be called when they go out of scope, and then the memory they use is freed). Local variables declared like this are allocated on the stack.
A static variables (with the static keyword, implying static storage duration, as opposed to automatic shown above. These just stay around for the duration of the program, and so don't have to be freed
on the heap, with dynamic allocation (new int or new int(42)). These have to be freed manually by calling delete.
So at the lowest level, you basically just have to preserve symmetry. If something was allocated with new, free it with delete,mallocis freed byfree, andnew[]bydelete[]`. And variables that are declared without any of these are automatically handled, and should not be manually freed.
Now, to keep memory management simple, RAII is typically used. The technique is based on the observation that only dynamically allocated objects have to be manually freed, and that local variables give you a very convenient hook for implementing custom actions when a local variable goes out of scope.
So, the dynamic allocation is wrapped up inside a separate class, which can be allocated as a local object on the stack. It can then, in its constructor, make any dynamic allocations you need, and its destructor cleans it up with the necessary delete calls.
This means that you essentially never have to call delete in your top-level code. It'll virtually always be hidden behind a RAII object's destructor. new calls become rare too, but are still used together with smart pointers (such as this: boost::shared_ptr<int>(new int(42)) which dynamically allocates an integer, and then passes it to a smart pointer which takes over ownership of it, and cleans it up automatically.
Both s1 and s2 are auto allocated. You don't delete those.
You only delete objects which you have created using new.
C++ knows three allocation modes: auto, static and dynamic. Read up on those.
Auto values, like your strings in the example are freed automatically when they leave scope. Their destructor is called automatically. Any memory that the strings allocated dynamically during their operation is freed when the string destructor is called.
Like everyone else said - no delete is needed here. Unless you see a new, you (generally) don't need a delete. I do want to add that s2 doesn't have a new string object. s2 is a string object from the time that it is declared. Assigning a slice of s1 to s2 modifies s2 so that it contains the same characters that are in the substring.
It's really important to understand what is going on here and it will become even more important the more you dig into C++. Oh, and congrats on learning a new language.
No, s2 does not need to be manually deleted. It is a local variable on the stack that will get automatically destroyed once it goes out of scope, just as it was automatically allocated when it was declared. Generally you only delete things that you allocated with new.
Temporary objects returned by functions are managed automatically and get destroyed by the end of the statement - if they are needed longer they get usually copied to a local variable before the temporary is destroyed (e.g. by a simple assignment like Object o = f(); or like in the line with the substr() call in your example).
If a function returns a pointer, the pointed-to object is not automatically managed like this. In the documentation should be noted who is responsible to delete the object once all work is done. As a default convention usually the one who allocated the object is responsible to delete it again, but the details need to be documented somewhere.
One of the most important concepts to understand in modern C++ (especially coming from a c background) is RAII. C++ encapsulates resources like memory (or mutexes, or transactions) inside classes that "acquire" the resource on construction (the string constructor allocates dynamic memory) and "release" it on destruction (destruction of the string class frees it). Since destruction of stack objects is deterministic (the stack based object expires when the enclosed scope does), the release doesn't have to be written, and will happen even if an exception is thrown.
So, no. In most of my coding, I never have a write an explicit delete (or delete[]), because either the resources are managed by string, an STL conatiner, or a shared_ptr or scoped_ptr.
why do you have to free s2 manually?
deletion of dynamic memory in s2 will be handled by the std::string destructor.