Destructor and smart pointers giving C2541 - c++

I'm trying to use some vectors of shared_ptr in my program, but doing so gives me a C2541-error: "delete": objects that are no pointers can't be deleted. I figured out it has something to do with the destructors of my classes (at least with one of them...) so i tried changing them - without success :(
My application contains a class A, which holds two vectors: one of shared_ptrs to objects of class B and of shared_ptrs to objects of class A.
Here are some parts of my code:
//A.cpp
A::~A(void)
{
for(std::vector<BPtr>::iterator it = allBs.begin(); it != allBs.end(); ++it)
{ //loop that deletes all Bs
delete it->get();
}
for(std::vector<APtr>::iterator it = allAs.begin(); it != allAs.end(); ++it)
{ //loop that (should) delete all As (and their As and Bs)
delete it->get();
delete it.operator*;
}
}
//A.h
class A
{
public:
typedef std::shared_ptr<A> APtr;
typedef std::shared_ptr<B> BPtr;
// some more stuff
private:
std::vector<BPtr> allBs;
std::vector<APtr> allAs;
}
I'm getting the error twice: one comes from the line
delete it.operator*;
and the other one is caused inside of memory.h.
I first had an extra recursive function which deleted the tree and was called by the destructor, but after a little thinking I thought that calling "delete" inside the destructor (line "delete it->get();") would do just the same.

You're doing it wrong.
The entire purpose of smart pointers like std::shared_ptr is that you do not have to manually delete what they point at. Indeed, you must not delete it manually. The smart pointer assumes ownership of the pointee—it will delete it itself when applicable. For std::shared_ptr, "when applicable" means "when the last std::shared_ptr pointing to the object is destroyed."
So just remove the destructor altogether, you don't need it. When the vectors are destroyed, they will destroy all of the contained std::shared_ptrs. This will reduce the reference count of the pointees. If any go to zero, they will be deleted automatically (by the shared_ptr destructor).

You don't want to delete a shared_ptr's contents, that's its job. simply reset the smart pointer:
it->reset();

You can and must delete only things created with new. Only these exactly once, nothing else. Deletion can be done either "by hand" or by letting a smart pointer like std::shared_ptr do it for you (which is a very good idea). When using smart pointers, you can (and should) get rid of the new in favor of std::make_shared or std::make_unique.
The same applies to new[] and delete[].
This means that in your destructor there is no room for delete because you never newed anything and have it owned by a raw pointer (which was good).

Related

Scalar deleting error when deleting std::shared_ptr

I am trying to find out how can I delete children of my Block class. I tried to do it with raw pointer. I don't know why, but it didn't work. I was getting the scalar deleting error. I now tried to do this with std::shared_ptr. I t didn't work as well. I am removing the children with:
void Block::remove(Block* block)
{
std::shared_ptr<Block> ptr(block);
auto it = std::find(children.begin(), children.end(), ptr);
if (it != children.end())
{
*it = NULL;
children.erase(it);
}
}
and the Block deleter is:
Block::~Block()
{
for (auto& child : this->children)
{
child = NULL;
}
if (!this->children.empty())
this->children.clear();
}
According to the debugging process, the ptr variable is found and then deleted. At the point of deleting everything works well until the last line, where I am getting the scalar deletion error. Just for the record: the children variable is of type std::vector<std::shared_ptr<Block>>.
EDIT:
The full code is here: https://github.com/DragonGamesStudios/Ages-of-Life. All the block functions are defined in AOLGuiLibrary/source/Block.cpp
You are mixing shared_ptrs with raw pointers, and that is a bad practice. If I understand correctly, you store the blocks in the vector of shared pointers, and that means that this vector has an ownership on these objects. When you create an additional shared_ptr out of a raw pointer you create another object that has the ownership on the same object:
std::shared_ptr<Block> ptr(block);
As the result, you would try to delete the object twice, and that leads to the undefined behavior.
First of all: do you need shared pointers? Consider using unique_ptr as a less error prone idea (if only one pointer object has the ownership, it is easier to understand who and when would destroy the underlying object).
Next, NEVER use raw pointers in this context: you may use raw pointers only when you don't store/delete the object. And for sure don't create smart pointers out of something that is already stored in one of them already.
Once a pointer has been given to a shared_ptr, that shared_ptr owns it. You must never again give that pointer to another shared pointer.
int * ptr = new int(1234);
{
std::shared_ptr<int> shp1(ptr); // shp1 owns ptr
std::shared_ptr<int> shp2(ptr); // shp2 owns ptr ???
}
// at this point ptr has been deleted twice
Note: it's preferable to not use new but to call std::make_shared and never give raw pointers to shared_ptr in the first place.
What you are doing to search for a child is exactly this problem. Passing in a raw pointer, you create a new owner for it. If that pointer is a child, it's already owned. You must not create shared pointers from raw pointers after they have been given to a shared pointer.
Also, the destructor you showed for Block isn't wrong, but it is completely unnecessary. All of what you coded there would happen automatically. Block is destroyed, it destroys the vector it holds (so clearing it is unnecessary.) The vector destroys its elements, so the shared pointers it holds are cleaned up too.
If block points at array code, this code is illegal, because for a new[] you have to call delete[], and std::shared_ptr<Block> would call delete. After that heap would be corrupted and further operations may fail. Same happens if blocks points to an element of array. If blocks points to object not located in heap, it also would result in error.
In general it's bad idea to delete a pointer passed to a function. There is no guarantee that the pointer was one returned by new, and even if it was: by which new?
To create a strong reference counter for an array, you have to use std::shared_ptr<Block[]>, but usually it's better idea to use some kind of container.
To find a value of pointer object in array of shared pointers:
auto it = std::find_if( children.begin(), children.end(), [=](auto& el) {
return el.get() == block;
});
If childrenis not static (that's not some kind of factory), then that destructor code is completely redundant. After call to ~Block() there will be calls to destructors of every member of Block, including that collection which would deallocate its resources and call destructor to every pointer, which would call destructor to every Block.

How to free a vector?

In my class I wrote
class Game {
private:
mtm::Dimensions dimensions;
std::vector<Character*> board;
public:
explicit Game(int height, int width):dimensions(height,width), board(height*width){
}
~Game() {}
};
But how should I free my vector, I think it leaks memory if I leave the d'tor empty.
If Game is not the owner it must not free the memory. The owner has to clean up.
If Game is the owner it can delete all elements in the destructor
~Game() {
for (auto &character : board) {
delete character;
}
}
The better way is to use smart pointers and remove the destructor
std::vector<std::unique_ptr<Character>> board;
You should try to follow the rule of 0
Assuming that your Game owns the objects, then your Game destructor would need to free up the memory. Presumably, the Characters are allocated with new. The below will delete all the Characters in the board, then the class variables (like the vector) will automatically be freed afterward.
~Game() {
for ( Character *character : board )
delete character;
}
Unless this is for an exercise with pointers, it's generally recommended not to use bare-pointers, and instead use a smart pointer, such as unique_ptr or shared_ptr.
std::vector<std::shared_ptr<Character>> board;
In this case, there will be no leak, since the Characters will automatically be freed once no one points to them anymore.
Use of shared_ptr vs unique_ptr is dependent on what you're doing.
The vector is a member variable. Member variables, like all sub objects are automatically destroyed when the super object is destroyed. The implicitly generated destructor does the right thing for vector.
Note that the vector contains pointers. If those pointers point to dynamically allocated objects, and are the only pointers to those objects, then those objects would have to be deleted, or else they would leak. If something else owns the pointed objects, then there is nothing that needs to be done in this destructor.
An example where the implicit destructor is correct. I pretend that the member is public for this example:
{
Character c;
Game g;
g.board.push_back(&c);
} // no leaks
Avoid owning bare pointers. Prefer to use RAII containers or smart pointers if you need ownership of dynamic objects.
the vector destructor won't leak memory you should write destructors for the types used in the vector. Also I wouldn't recommend a pointer to something which dosen't destruct itself.
I think what you are looking for are smart pointers.

destructing an object stored in the vector of pointers [duplicate]

This question already has answers here:
Does std::list::remove method call destructor of each removed element?
(6 answers)
Closed 9 years ago.
I have a class that contains pointers, the class inherits nothing
class MyClass
{
public:
MyClass();
~MyClass();
private:
//i have pointers here
};
MyClass::~MyClass()
{
print("destroyed..");
}
Now i have to use this class as a pointer in vector like this:
vector<MyClass*> classes;
Push some classes in here but when i remove an element:
classes.remove(index);
The destructor doesn't get called,and i think that I have a memory leak.
So how do i make it call the destructor
A vector of pointers does nothing to delete the pointers when they get removed or cleared from it. The vector cannot know if the pointers are dynamically allocated or not. It is not it's job to call delete.
It is up to you to call delete on the pointers, if and when it is necessary. There are not enough details in your question to determine whether it is necessary at all (you haven't shown how the objects pointed to are allocated). But since you claim there is a memory leak, this could indicate that they are dynamically allocated. The immediate solution is to call delete:
delete *it;
classes.erase(it); // vector has no remove member function
A safer solution is to store unique ownership smart pointers, such as std::unique_ptr<MyClass>. The standard library also provides smart pointers for shared and weak ownership. See Smart Pointers.
All the above is assuming that you do actually need to store a pointer. In general, it is safer and clearer to store values:
std::vector<MyClass> classes; // but don't call it "classes". A vector stores objects.
That's one of the reasons why you should avoid using std::vector<MyClass*> at first place. There's an ugly memory management connected with it and it won't stay as easy as classes.remove(index);
Basically, for every new a delete must be called and for every new[] a delete[] must be called, no matter whether you use this pointer as a local variable or you put it into the vector:
vector<MyClass*> vec;
vec.push_back(new MyClass()); // <-- object has been created
...
delete classes[index]; // <-- object shall be destructed
// the delete call will automatically invoke the destructor if needed
...
// now you can remove the dangling pointer from the vector
Just note that once the object has been destructed, any (old) reference to this object is invalid and trying to access this object using such reference (dangling pointer) will yield undefined behavior.
Firstly, std::vector has no remove, you probably mean erase.
Secondly, you need to manually call delete on whatever you're removing:
vector<MyClass*> classes;
auto iter = <iterator to index to remove>;
delete *iter;;
classes.erase(iter);
Or, to avoid all this pain, use a std::unique_ptr<MyClass>.
It is unclear who is responsible for managing the lifetime of the objects pointed by the pointers inside classes. Have you pushed newed pointers into it, or have you pushed the addresses of automatic storage objects?
If you have done the former, then you must manually delete the pointer before removing it. Else, if you have done the latter, then you could just leave it as is, just leaving the pointed-to objects destroy themselves as they leave their respective scopes. If you have mixed newed and non-newed pointers, whose possibility isn't that remote as you would think, then you're definitely damned, undefined behavior making demons fly out of your nose.
These kinds of situations involving pointers are very ambiguous, and it is generally recommended not to use pointers at all, and make the std::vector store plain objects, which makes your object lifetime management much simpler and the making the declaration just speak for itself.
vector<MyClass> classes; // Do this instead
You have to manually delete your pointers before your application exit or after your class object is removed from vector.
// Delete all
vector<MyClass*>::iterator it = classes.begin();
while (it != classes.end()) {
delete *it;
it = classes.erase(it);
}
Tip: Never add stack constructed pointers like following:
MyClass m;
classes.push_back(&m);
Edit: As suggested by other member the better solution is:
MyClass m(/* ... */);
vector<MyClass> classes;
classes.push_back(m);
However please note, you have to properly implement the copy constructor especially if your class has pointer data members that were created with new.
Make a temp pointer to hole MyClass* pointer before you remove it from your vector.
vector<MyClass*> classes;
//push some classes in here but
//when i remove an element
MyClass* temp = classes[index];
classes.remove(index);
// call delete temp; if you want to call the destructor thus avoid memory leak.
delete temp;
To avoid memory leak, remember never to loose control of heap object, always keep a a pointer or reference to it before object release.
It seems that you want your vector to be manager of your items.
Take a look at boost::ptr_vector class
its basically a wrapper around std::vector class.
You declare that this vector is the "holder" of these pointers, and if you remove them from this containers you want them to be deleted.
#include <boost/ptr_container/ptr_vector.hpp>
...
boost::ptr_vector<MyClass> myClassContainer;
myClassContainer.push_back(new MyClass());
myClassContainer.clear(); // will call delete on every stored object!

How to destroy a vector of pointers in c++?

I have the following code in one of my methods:
vector<Base*> units;
Base *a = new A();
Base *b = new B();
units.push_back(a);
units.push_back(b);
Should I destroy the a and b pointers before I exit the method?
Or should I somehow just destroy the units vector of pointers?
Edit 1:
This is another interesting case:
vector<Base*> units;
A a;
B b;
units.push_back(&a);
units.push_back(&b);
What about this case? Now I don't have to use delete nor smart pointers.
Thanks
If you exit the method, units will be destroyed automatically. But not a and b. Those you need to destroy explicitly.
Alternatively, you could use std::shared_ptr to do it for you, if you have C++11.
std::vector<std::shared_ptr<Base>> units;
And you just use the vector almost as you did before, but without worrying about memory leaks when the function exists. I say almost, because you'll need to use std::make_shared to assign into the vector.
A rather old-fashioned solution, that works with all compilers:
for ( vector<Base*>::iterator i = units.begin(); i != units.end(); ++i )
delete *i;
In C++11 this becomes as simple as:
for ( auto p : units )
delete p;
Your second example doesn't require pointer deallocation; actually it would be a bad error to do it. However it does require care in ensuring that a and b remain valid at least as long as units does. For this reason I would advise against that approach.
You need to iterate over the vector and delete each pointer it contains. Deleting the vector will result in memory leaks, as the objects pointed to by its elements are not deleted.
TL;DR: The objects remain, the pointers are lost == memory leak.
Yes you should destroy those pointers (assuming you aren't returning the vector elsewhere).
You could easily do it with a std::for_each as follows:
std::for_each( units.begin(), units.end(), []( Base* p ) { delete p; } );
You should not delete if this two situation match.
Created vector return to out side of the function.
Vector created outside of the function and and suppose to access from other functions.
In other situations you should delete memory pointed by pointers in vector. otherwise after you delete the pointers, no way to refer this memory locations and it calls memory leak.
vector<Base*>::iterator it;
for ( it = units.begin(); it != units.end(); ){
delete * it;
}
I would suggest that you use SmartPointers in the vector. Using smart pointers is a better practice than using raw pointers. You should use the std::unique_ptr, std::shared_ptr or std::weak_ptr smart pointers or the boost equivalents if you don't have C++11. Here is the boost library documentation for these smart pointers.
In the context of this question, yes you have to delete the pointers that are added to the vector. Else it would cause a memory leak.
You have to delete them unless you will have memory leak , in the following code if I comment the two delete lines the destructors never called, also you have to declare the destuctor of the Base class as virtual. As others mentioned is better to use smart pointers.
#include <iostream>
#include <vector>
class Base
{
public:
virtual ~Base(){std::cout << "Base destructor" << std::endl;};
};
class Derived : public Base
{
~Derived(){std::cout << "Derived destructor" << std::endl;};
};
int main()
{
std::vector<Base*> v;
Base *p=new Base();
Base *p2=new Derived();
v.push_back(p);
v.push_back(p2);
delete v.at(0);
delete v.at(1);
};
Output:
Base destructor
Derived destructor
Base destructor
Output with non-virtual base destructor (memory leak):
Base destructor
Base destructor
Yes and no. You don't need to delete them inside the function, but for other reasons than you might think.
You are essentially giving ownership of the objects to the vector, but the vector is not aware of that and therfore wont call delete on the pointers automatically. So if you store owning raw pointers in a vector, you have to manually call delete on them some time. But:
If you give the vector out of your function, you should not destroy the objects inside the function, or the vector full of pointers to freed memory would be pretty useless, so no. But in that case, you should make sure the objects are destroyed after the vector has been used outside the function.
If you don't give the vector out of the function, you should destroy the objects inside the function, but there would be no need to allocate them on the free store, so don't use pointers and new. You just push/emplace the objects themselves into the vector, it takes care of the destruction then, and therfore you don't need delete.
And besides that: Don't use plain new. Use smart pointers. Regardless what you do with them, the smart pointers will take care of a proper destruction of the objects contained. No need to use new, no need to use delete. Ever. (Except when you are writing your own low level data structures, e.g. smart pointers). So if you want to have a vector full of owning pointers, these should be smart pointers. That way you won't have to worry about wether, when and how to destroy the objects and free the memory.
The best way to store pointers in a vector will be to use smart_ptr instead of raw pointers. As soon as the vector DTOR is called and control exits the DTOR all smart_ptrs will be refernced counted. And you should never bothered about the memory leak with smart_ptrs.
In the first example, you will eventually have to delete a and b, but not necessarily when units goes out of scope. Usually you will do that just before units goes out of scope, but that is not the only possible case. It depends on what is intended.
You might (later in the same function) alias a or b, or both, because you want them to outlive units or the function scope. You might put them into two unit objects at the same time. Or, many other possible things.
What's important is that destroying the vector (automatic at scope end in this case) destroys the elements held by the vector, nothing more. The elements are pointers, and destroying a pointer does nothing. If you also want to destroy what the pointer points to (as to not leak memory), you must do that manually (for_each with a lambda would do).
If you don't want to do this work explicitly, a smart pointer can automatize that for you.
The second example (under Edit1) does not require you to delete anything (in fact that's not even possible, you would likely see a crash attempting to do that) but the approach is possibly harmful.
That code will work perfectly well as long as you never reference anything in units any more after a and b left scope. Woe if you do.
Technically, such a thing might even happen invisibly, since units is destroyed after a, but luckily, ~vector does not dereference pointer elements. It merely destroys them, which for a pointer doesn't do anything (trivial destructor).
But imagine someone was so "smart" as to extend the vector class, or maybe you apply this pattern some day in the future (because it "works fine") to another object which does just that. Bang, you're dead. And you don't even know where it came from.
What I really don't like about the code, even though it is strictly "legal" is the fact that it may lead to a condition which will crash or exhibit broken, unreproducable behaviour. However, it does not crash immediately. Code that is "broken" should crash immediately, so you see that something is wrong, and you are forced to fix it. Unluckily that's not the case here.
This will appear to work, possibly for years, until one day it doesn't. Eventually you'll have forgotten that a and b live on the current stack frame and reference the non-existing objects in the vector from some other location. Maybe you dynamically allocate the vector in a future revision of your code, since you pass it to another function. And maybe it will continue to appear working.
And then, you'll spend hours of your time (and likely the time of others) trying to find why a section of code that cannot possibly fail produces wrong results or crashes.
Warning against your second example.
This simple extension leads to undefined behavior:
class A {
public:
int m;
A(int _m): m(_m) {}
};
int main(){
std::vector<A*> units;
for (int i = 0; i < 3; ++i) {
A a(i);
units.push_back(&a);
}
for (auto i : units) std::cout << i->m << " "; // output: 2 2 2 !!!!
return 0;
}
In each loop, the pointer to each a is saved in units, but the objects that they point to go out of scope. In the case of my compiler, the memory address of each a was re-used each time, resulting in units holding three identical memory addresses -- all pointing to the final a object.

When is a C++ destructor called?

Basic Question: when does a program call a class' destructor method in C++? I have been told that it is called whenever an object goes out of scope or is subjected to a delete
More specific questions:
1) If the object is created via a pointer and that pointer is later deleted or given a new address to point to, does the object that it was pointing to call its destructor (assuming nothing else is pointing to it)?
2) Following up on question 1, what defines when an object goes out of scope (not regarding to when an object leaves a given {block}). So, in other words, when is a destructor called on an object in a linked list?
3) Would you ever want to call a destructor manually?
1) If the object is created via a pointer and that pointer is later deleted or given a new address to point to, does the object that it was pointing to call its destructor (assuming nothing else is pointing to it)?
It depends on the type of pointers. For example, smart pointers often delete their objects when they are deleted. Ordinary pointers do not. The same is true when a pointer is made to point to a different object. Some smart pointers will destroy the old object, or will destroy it if it has no more references. Ordinary pointers have no such smarts. They just hold an address and allow you to perform operations on the objects they point to by specifically doing so.
2) Following up on question 1, what defines when an object goes out of scope (not regarding to when an object leaves a given {block}). So, in other words, when is a destructor called on an object in a linked list?
That's up to the implementation of the linked list. Typical collections destroy all their contained objects when they are destroyed.
So, a linked list of pointers would typically destroy the pointers but not the objects they point to. (Which may be correct. They may be references by other pointers.) A linked list specifically designed to contain pointers, however, might delete the objects on its own destruction.
A linked list of smart pointers could automatically delete the objects when the pointers are deleted, or do so if they had no more references. It's all up to you to pick the pieces that do what you want.
3) Would you ever want to call a destructor manually?
Sure. One example would be if you want to replace an object with another object of the same type but don't want to free memory just to allocate it again. You can destroy the old object in place and construct a new one in place. (However, generally this is a bad idea.)
// pointer is destroyed because it goes out of scope,
// but not the object it pointed to. memory leak
if (1) {
Foo *myfoo = new Foo("foo");
}
// pointer is destroyed because it goes out of scope,
// object it points to is deleted. no memory leak
if(1) {
Foo *myfoo = new Foo("foo");
delete myfoo;
}
// no memory leak, object goes out of scope
if(1) {
Foo myfoo("foo");
}
Others have already addressed the other issues, so I'll just look at one point: do you ever want to manually delete an object.
The answer is yes. #DavidSchwartz gave one example, but it's a fairly unusual one. I'll give an example that's under the hood of what a lot of C++ programmers use all the time: std::vector (and std::deque, though it's not used quite as much).
As most people know, std::vector will allocate a larger block of memory when/if you add more items than its current allocation can hold. When it does this, however, it has a block of memory that's capable of holding more objects than are currently in the vector.
To manage that, what vector does under the covers is allocate raw memory via the Allocator object (which, unless you specify otherwise, means it uses ::operator new). Then, when you use (for example) push_back to add an item to the vector, internally the vector uses a placement new to create an item in the (previously) unused part of its memory space.
Now, what happens when/if you erase an item from the vector? It can't just use delete -- that would release its entire block of memory; it needs to destroy one object in that memory without destroying any others, or releasing any of the block of memory it controls (for example, if you erase 5 items from a vector, then immediately push_back 5 more items, it's guaranteed that the vector will not reallocate memory when you do so.
To do that, the vector directly destroys the objects in the memory by explicitly calling the destructor, not by using delete.
If, perchance, somebody else were to write a container using contiguous storage roughly like a vector does (or some variant of that, like std::deque really does), you'd almost certainly want to use the same technique.
Just for example, let's consider how you might write code for a circular ring-buffer.
#ifndef CBUFFER_H_INC
#define CBUFFER_H_INC
template <class T>
class circular_buffer {
T *data;
unsigned read_pos;
unsigned write_pos;
unsigned in_use;
const unsigned capacity;
public:
circular_buffer(unsigned size) :
data((T *)operator new(size * sizeof(T))),
read_pos(0),
write_pos(0),
in_use(0),
capacity(size)
{}
void push(T const &t) {
// ensure there's room in buffer:
if (in_use == capacity)
pop();
// construct copy of object in-place into buffer
new(&data[write_pos++]) T(t);
// keep pointer in bounds.
write_pos %= capacity;
++in_use;
}
// return oldest object in queue:
T front() {
return data[read_pos];
}
// remove oldest object from queue:
void pop() {
// destroy the object:
data[read_pos++].~T();
// keep pointer in bounds.
read_pos %= capacity;
--in_use;
}
~circular_buffer() {
// first destroy any content
while (in_use != 0)
pop();
// then release the buffer.
operator delete(data);
}
};
#endif
Unlike the standard containers, this uses operator new and operator delete directly. For real use, you probably do want to use an allocator class, but for the moment it would do more to distract than contribute (IMO, anyway).
When you create an object with new, you are responsible for calling delete. When you create an object with make_shared, the resulting shared_ptr is responsible for keeping count and calling delete when the use count goes to zero.
Going out of scope does mean leaving a block. This is when the destructor is called, assuming that the object was not allocated with new (i.e. it is a stack object).
About the only time when you need to call a destructor explicitly is when you allocate the object with a placement new.
1) Objects are not created 'via pointers'. There is a pointer that is assigned to any object you 'new'. Assuming this is what you mean, if you call 'delete' on the pointer, it will actually delete (and call the destructor on) the object the pointer dereferences. If you assign the pointer to another object there will be a memory leak; nothing in C++ will collect your garbage for you.
2) These are two separate questions. A variable goes out of scope when the stack frame it's declared in is popped off the stack. Usually this is when you leave a block. Objects in a heap never go out of scope, though their pointers on the stack may. Nothing in particular guarantees that a destructor of an object in a linked list will be called.
3) Not really. There may be Deep Magic that would suggest otherwise, but typically you want to match up your 'new' keywords with your 'delete' keywords, and put everything in your destructor necessary to make sure it properly cleans itself up. If you don't do this, be sure to comment the destructor with specific instructions to anyone using the class on how they should clean up that object's resources manually.
Pointers -- Regular pointers don't support RAII. Without an explicit delete, there will be garbage. Fortunately C++ has auto pointers that handle this for you!
Scope -- Think of when a variable becomes invisible to your program. Usually this is at the end of {block}, as you point out.
Manual destruction -- Never attempt this. Just let scope and RAII do the magic for you.
To give a detailed answer to question 3: yes, there are (rare) occasions when you might call the destructor explicitly, in particular as the counterpart to a placement new, as dasblinkenlight observes.
To give a concrete example of this:
#include <iostream>
#include <new>
struct Foo
{
Foo(int i_) : i(i_) {}
int i;
};
int main()
{
// Allocate a chunk of memory large enough to hold 5 Foo objects.
int n = 5;
char *chunk = static_cast<char*>(::operator new(sizeof(Foo) * n));
// Use placement new to construct Foo instances at the right places in the chunk.
for(int i=0; i<n; ++i)
{
new (chunk + i*sizeof(Foo)) Foo(i);
}
// Output the contents of each Foo instance and use an explicit destructor call to destroy it.
for(int i=0; i<n; ++i)
{
Foo *foo = reinterpret_cast<Foo*>(chunk + i*sizeof(Foo));
std::cout << foo->i << '\n';
foo->~Foo();
}
// Deallocate the original chunk of memory.
::operator delete(chunk);
return 0;
}
The purpose of this kind of thing is to decouple memory allocation from object construction.
Remember that Constructor of an object is called immediately after the memory is allocated for that object and whereas the destructor is called just before deallocating the memory of that object.
Whenever you use "new", that is, attach an address to a pointer, or to say, you claim space on the heap, you need to "delete" it.
1.yes, when you delete something, the destructor is called.
2.When the destructor of the linked list is called, it's objects' destructor is called. But if they are pointers, you need to delete them manually.
3.when the space is claimed by "new".
Yes, a destructor (a.k.a. dtor) is called when an object goes out of scope if it is on the stack or when you call delete on a pointer to an object.
If the pointer is deleted via delete then the dtor will be called. If you reassign the pointer without calling delete first, you will get a memory leak because the object still exists in memory somewhere. In the latter instance, the dtor is not called.
A good linked list implementation will call the dtor of all objects in the list when the list is being destroyed (because you either called some method to destory it or it went out of scope itself). This is implementation dependent.
I doubt it, but I wouldn't be surprised if there is some odd circumstance out there.
If the object is created not via a pointer(for example,A a1 = A();),the destructor is called when the object is destructed, always when the function where the object lies is finished.for example:
void func()
{
...
A a1 = A();
...
}//finish
the destructor is called when code is execused to line "finish".
If the object is created via a pointer(for example,A * a2 = new A();),the destructor is called when the pointer is deleted(delete a2;).If the point is not deleted by user explictly or given a new address before deleting it, the memory leak is occured. That is a bug.
In a linked list, if we use std::list<>, we needn't care about the desctructor or memory leak because std::list<> has finished all of these for us. In a linked list written by ourselves, we should write the desctructor and delete the pointer explictly.Otherwise, it will cause memory leak.
We rarely call a destructor manually. It is a function providing for the system.
Sorry for my poor English!