Do I leak if I allocate memory with new in the constructor of an object and immediately after I throw an exception?
The object shouldn't be constructed at all and thus no destructor will be called, but what about that memory?
e.g.
MyObject() {
data = new char[200]; // Will this be leaked?
if(something_is_wrong)
throw exception();
}
It will leak. Once you have gotten a pointer from new it eventually needs to be deleted. The solution is to make data a smart pointer (or in this case, probably a std::string); while MyObject's destructor won't be called, data members' destructors are called.
Yes, it will be a leak unless data is kind of handle, smart pointer and not a raw pointer char* data. A safe variant of this is:
class MyObject {
std::vector<char> data; // or some handle/smart pointer (i.e. unique_ptr)
// it might be just std::string
public:
MyObject( int sz) : data( sz) {}
};
In this case the memory used is now managed by vector. You can of course do it by yourself what is actually done in vector already and is exception safe. This is you can use approach similar to std::uninitialized_fill.
Unless data is a smart pointer (or, more generally, any object that frees the memory passed to it when it destructs) you will leak memory.
The new will need to be balanced with a delete[] (note the []). It's important to note that, since a MyObject instance was not created, the destructor to MyObject will not be called so you cannot rely on any memory cleanup there.
Two alternatives.
free the memory before the throw statement.
Make data a smart pointer (if it isn't already).
2 is preferred - by exploiting RAII it makes code more stable.
The situation that you sketch,
MyObject() {
data = new char[200]; // Will this be leaked?
if(something_is_wrong)
throw exception();
}
will1 leak unless automatic garbage collection is used (and even so it may still leak).
This case is very easily dealt with by using an appropriate standard library container:
MyObject()
{
string data( 200, '\0' );
if(something_is_wrong)
throw exception();
}
And in general preferentially use standard library containers instead of all this new'ing, and if there isn't a suitable container, use smart pointers such as std::unique_ptr.
In short, there's not really a problem, not any more than a call to std::terminate is a problem (just remove the call, or don't do it in the first place).
However, if you define a custom allocation function for the class, and forget to define a corresponding deallocation function, then throwing an exception from a constructor can leak memory.
As a learner simply don't define allocation functions.
As a professional remember to do it properly if at some time you should really need it.
1) Under the reasonable assumption that you're not using a smart pointer to guarantee cleanup and asking this question without mentioning the smart pointer.
Related
I read here that
As long as you’re careful, it’s okay (not evil) for an object to
commit suicide (delete this).
Here’s how I define “careful”:
You must be absolutely 100% positively sure that this object was allocated
via new (not by new[], nor by placement new, nor a local object on the
stack, nor a namespace-scope / global, nor a member of another object;
but by plain ordinary new).
If I use placement new, what alternatives do I have?
Placement new is used to separate memory allocation and object lifetime, so you would usually call the destructor explicitly:
myobj->~myclass();
and free the memory later, or continue to use the memory for other purposes.
Placement new means the object is not allocated on the heap, but memory for its storage is provided by the user. Delete in this case would try to deallocate a non-heap block, which is usually fatal...
There's nothing to delete, so you have to do an explicit destructor call:
struct SomeClass {
SomeClass() { std::cout << "Constuctor\n"; }
~SomeClass() { std::cout << "Destructor\n"; }
};
std::aligned_storage<sizeof(SomeClass), alignof(SomeClass)>::type storage;
new(&storage) SomeClass();
reinterpret_cast< SomeClass* >(&storage) -> ~SomeClass();
Having a this pointer only is not enough to do proper destruction in a general case.
Since the arrival of std::shared_ptr and std::unique_ptr it has become un-necessary (and undesirable) to write objects that manage their own lifetimes.
Good c++ form requires that one object has one responsibility. Your object's responsibility is the work it performs. The responsibility of a smart pointer is to manage its lifetime.
There is one remaining scenario where you would need to delete this - when writing an object for an old API that demands intrusive reference counting.
Suppose I have a function or class that maintains some pointers to other data objects, like so:
class MyObject {
...
AnotherObject* o1, *o2;
SomeObject* s1, *s2;
...
}
int main() {
...
MyObject mo1 = new MyObject();
... // do stuff with mo1
delete mo1;
}
Suppose they are assigned valid pointer values from elsewhere during/after initialization.
When I destroy the MyObject object after assigning those pointers inside, can a memory leak result if I do not null the pointers during destruction like so?:
MyObject::~MyObject() {
o1 = nullptr;
o2 = nullptr;
...
}
Thanks.
No it won't cause a memory leak. Note however that this:
MyObject mo1 = new MyObject();
// do stuff with mo1
delete mo1;
will result in a memory leak if do stuff with mo1 throws an exception (which could be the case if it comprises references to nullptr). Therefore it's advisable not to use naked pointers like you do but smart pointers instead - this way RAII guarantees that your pointer will be deleted.
It sounds like you come from a Java background, where setting pointers to null is necessary to allow the garbage collector to reclaim other objects. If so, the answer is simple: no, that's not how it works in C++. Setting a pointer to null has no bearing whatsoever on memory usage, and there is no garbage collector anyway that could reclaim any memory.
Instead you are supposed to consider ownership. Most objects have one specific owner; once that owner is deleted, so are its owned objects. This is most conveniently modelled using unique_ptr instead of raw pointers. For objects that have more complex ownership, there is shared_ptr and weak_ptr.
Once again, there is no garbage collector, so any time you use new to create an object, somehow, somewhere there must be a corresponding delete. The easiest way to ensure such deletes are not forgotten is to use unique_ptr.
Also be wary of using new too often. Your mo1 object can be allocated on the stack without any problem: it's lifetime is limited to one function (main), so why not use simply allocate it as MyObject mo1; - that's enough, no need to new or delete anything.
No it would not. Memory leak happens because of a non-deleted memory which was allocated using new. Nulling a pointer is just a way to check it later if it was deleted or not and it has nothing to do with memory leak.
On the other hand, dealing with memory manually is not a the best way to achieve what you want. Smart pointers are exist (std::shared_ptr, std::unique_ptr...). You should have a look on them.
What I understand from RAII is whenever you need to allocate memory manually with new etc. you need to free it too. So, instead of freeing it manually, you should create classes with constructor and destructor to do the job.
So, what are the following people talking about?
From: The meaning of the term - Resource Acquisition Is Initialization
The problem is that int * p = malloc(1000); is also initialization of an (integer) object, but it's not the kind of initialization we mean in the context of RAII.
...
#Fred: Indeed. int* is not a RAII type because it doesn't do cleanup. So it's not what RAII means, even though it is what RAII literally says.
Well, I know malloc is used in C, and new is used in C++.
Using malloc per se is not RAII because the resources are not freed when the variable goes out of scope, causing leaks of memory. You can make it RAII if you wrap this inside a class and free the resources in the destructor, because local class instances do die when they go out of scope. However, it should be noted what is being discussed here: the int * type is not RAII, and if you enclose it in a RAII type it still isn't. The wrapper doesn't make it RAII, so the RAII type here is the wrapper, not the pointer itself.
As requested in the comments: RAII stands for Resource Acquisition Is Initialisation and it's a design paradigm that combines the allocation of resources with the initialisation and destruction of objects. You don't seem far from understanding it: when an object is instantiated it allocates all the necessary resources (memory, file descriptors, streams, and so on) and frees them when it goes out of scope or the object is otherwise destructed. This is a common paradigm in C++ because C++ classes are RAII (that is, they die when they go out of scope) and as such it's easy to guarantee proper cleanup. The obvious upside being that you don't need to worry about manual cleanup and tracking variable lifetime.
On a related note, notice that this refers to stack allocation, not heap. What this means is that whatever the means you use for allocation (new/malloc vs delete/free) it still isn't RAII; memory that is allocated dynamically does not get magically freed, that's a given. When a variable is allocated on the stack (local variables) they are destroyed when the scope dies.
Example:
class MyObject
{
public:
MyObject()
{
// At this point resources are allocated (memory, files, and so on)
// In this case a simple allocation.
// malloc would have been just as fine
this->_ptr = new int;
}
~MyObject()
{
// When the object is destructed all resources are freed
delete this->_ptr;
}
private:
int * _ptr;
};
The previous sample code implements a RAII wrapper over a native pointer. Here's how to use it:
void f()
{
MyObject obj;
// Do stuff with obj, not including cleanup
}
In the previous example the int pointer is allocated when the variable is instantiated (at declaration time) and freed when the f call terminates, causing the variable to go out of scope and calling its destructor.
Note: As mentioned in the comments by Jarod42 the given example does not conform to the rule of 3 or the rule of 5, which are common thumb rules in C++. I would rather not add complexity to the given example, and as such I'll complete it here. These rules indicate that, if a method from a given set is implemented, then all methods of the set should be implemented, and those methods are the copy and move constructors, the assignment and move operators, and the destructor. Notice at first that this is a general rule, which means that is not mandatory. For instance, immutable objects should not implement assignment and move operators at all. In this case, if the object is to implement these operators it would probably imply reference counting, as multiple copies of the resource exist the destructor must not free the resources until all copies are destroyed. I believe that such an implementation would fall out of scope and as such I'm leaving it out.
By example
NOT RAII:
void foo()
{
int* p = malloc(sizeof(int) * N);
// do stuff
free(p);
}
also NOT RAII:
void foo()
{
int* p = new int[N];
// do stuff
delete[] p;
}
RAII:
struct MyResourceManager
{
int* p;
MyResourceManager(size_t n) : p(malloc(sizeof(int) * n)) { }
~MyResourceManager() { free(p); }
};
void foo()
{
MyResourceManager resource(N);
// doing stuff with resource.p
}
Also RAII (better):
struct MyResourceManager
{
int* p;
MyResourceManager(size_t n) : p(new int[n]) { }
~MyResourceManager() { delete[] p; }
};
void foo()
{
MyResourceManager resource(N);
// doing stuff with resource.p
}
Also RAII (best for this use case):
void foo()
{
std::unique_ptr<int[]> p(new int[N]);
// doing stuff with p
}
RAII is not use of operator new nor is it use of malloc().
It essentially means that, in the process of initialising an object, all resources that object needs to function are allocated. The counterpart requirement is that, in the process of destroying the object, that the resources it has allocated are released.
The concept applies to memory (most commonly), but also to any other resource that needs to be managed - file handles (opened in initialisation, closed when done), mutexes (grabbed in initialisation, released when done), communication ports, etc etc.
In C++, RAII is typically implemented by performing initialisation in constructors of an object, and the release of resources is done in the destructor. There are wrinkles such as other member functions possibly reallocating (e.g. resizing a dynamically allocated array) - in those cases, the member functions must ensure they do things in a way to ensure all resources allocated are appropriately released when the destructor is done. If there are multiple constructors, they need to do things consistently. You'll see this described as something like the constructor setting a class invariant (i.e. that resources are allocated correctly), member functions maintaining that invariant, and the destructor being able to clean up because the invariant is maintained.
The advantage of RAII - if done right - is that non-static variable lifetime is managed by the compiler (when an object goes out of scope, its destructor is invoked). So, the resources will be cleaned up correctly.
However, the requirement is always that the destructor does the cleanup (or that data members of the class have their own destructors that do the required cleanup). If constructor initialises an int * using malloc(), then it is not enough to assume the destructor will clean up - the destructor must pass that pointer to free(). If you don't do that, the C++ compiler will not magically find some way to release the memory for you (the pointer will no longer exist when the destructor is done, but the allocated memory it pointed to will not be released - so the result is a memory leak). C++ does not inherently use garbage collection (which is a trap for people used to garbage collected languages assuming that garbage collection will occur).
And it is undefined behaviour to use malloc() to allocate memory, and operator delete in any form to release it.
It is generally preferable to not use malloc() and free() in C++, because they do not work well with object construction and destruction (invoking constructors and destructors). Use operator new instead (and for whatever form of operator new you use, use the corresponding operator delete). Or, better yet, use standard C++ containers (std::vector, etc) as much as possible to avoid the need to worry about manually releasing memory you allocate.
Destruction of int* doesn't release the resources. It isn't safe to just let it go out of scope, so it isn't RAII.
The int * could be be a member of a class that deletes the int* in its destructor, which is essentially what unique_ptr of an int does. You make things like this RAII by wrapping them in code that encapsulates the deletion.
The discussion is about code that literally does initialization upon resource acquisition, but doesn't follow the RAII design.
In the shown example with malloc, 1000 bytes of memory are allocated (resource allocation) and a variable p (pointer to int) is initialized with the result (initialization). However, this is obviously not an example of RAII, because the object (of type int *) doesn't take care of the acquired resource in its destructor.
So no, malloc itself can not be RAII in some situations, it is an example of non-RAII code that nevertheless does "Initialization on Resource Acquisition" which might be confusing for new c++ programmers on first glance.
In C++, unique_ptr represents a pointer that "owns" the thing it points to. You can supply the release function as second argument:
std::unique_ptr<int[], std::function<void(void*)>>
p( (int *)malloc(1000 * sizeof(int)), std::free );
Of course, there's not much reason to do this instead of just using new (when the default deleter delete will do the right thing).
Yes, you can deal with int * p = malloc(1000); using the RAII paradigm. Smart pointers and std::vector use a very similar technique though they don't probably use malloc and prefer to use new instead.
Here's a very simplistic look at what one can do with malloc. MyPointer is far from being useful in a real application. Its only purpose is to demonstrate the principle of RAII.
class MyPointer
{
public:
MyPointer(size_t s) : p(malloc(s)) {}
~MyPionter() { free(p); }
int& operator[](size_t index) { return p[index]; }
private:
int* p;
};
int main()
{
// By initializing ptr you are acquiring resources.
// When ptr gets destructed, the resource is released.
MyPointer ptr(1000);
ptr[0] = 10;
std::cout << ptr[0] << std::endl;
}
The core idea behind RAII is:
Treat resource acquisition as though you are initializing an object.
Make sure the acquired resource(s) is(are) released when the object is destructed.
You can read more on RAII at Wikepedia.
So, what are the following people talking about?
What is RAII?
RAII in a nutshell is a very simple idea. It is the idea that no object may exist at all unless it is fully initialised.
Why is that good?
We now have a concrete guarantee that a 'half built' object cannot be accidentally used - because at no point in the logical flow of the program can it possibly exist.
How do we achieve it?
a) always manage resources (memory, files, mutex locks, database connections) in a class of their own which is specifically tailored to only managing that resource.
b) build complex logic out of collections of objects covered by [a]
c) Always throw if anything in the constructor fails (to guarantee that a failed object cannot exist)
d) if we are managing more than one resource in a class, we ensure that a failed construction cleans up the parts that have already been constructed (NOTE: this is hard [sometimes impossible], and why at this point you should be referred back to [a])
Sounds hard?
Initialising your objects completely in the initialiser list, while wrapping all external resources in a manager class (e.g. files, memory) achieves perfect RAII effortlessly.
What's the advantage?
Your program may now contain only logic which makes it easier to reason about and to read. The compiler will take care of all resource management perfectly.
Effortless Compound Resource Management
An example of RAII that's hard without manager classes and easy with them?
struct double_buffer
{
double_buffer()
: buffer1(std::nullptr) // NOTE: redundant zero construction
, buffer2(std::nullptr)
{
buffer1 = new char[100]; // new can throw!
try {
buffer2 = new char[100]; // if this throws we have to clean up buffer1
}
catch(...) {
delete buffer1; // clean up buffer1
throw; // rethrow because failed construction must throw!
}
}
// IMPORTANT!
// you MUST write or delete copy constructors, move constructor,
// plus also maybe move-assignment or move-constructor
// and you MUST write a destructor!
char* buffer1;
char* buffer2;
};
now the RAII version:
struct double_buffer
{
double_buffer()
: buffer1(new char[100]) // memory immediately transferred to manager
, buffer2(new char[100]) // if this throws, compiler will handle the
// correct cleanup of buffer1
{
// nothing to do here
}
// no need to write copy constructors, move constructor,
// move-assignment or move-constructor
// no need to write destructor
std::unique_ptr<char[]> buffer1;
std::unique_ptr<char[]> buffer2;
};
How does it improve my code?
some safe code that uses RAII:
auto t = merge(Something(), SomethingElse()); // pretty clear eh?
t.performAction();
the same code that does not use RAII:
TargetType t; // at this point uninitialised.
Something a;
if(a.construct()) {
SomethingElse b;
if (b.construct()) {
bool ok = merge_onto(t, a, b); // t maybe initialised here
b.destruct();
a.destruct();
if (!ok)
throw std::runtime_error("merge failed");
}
else {
a.destruct();
throw std::runtime_error("failed to create b");
}
}
else {
throw std::runtime_error("failed to create a");
}
// ... finally, we may now use t because we can (just about) prove that it's valid
t.performAction();
The difference
The RAII code is written solely in terms of logic.
The non-RAII code is 40% error handling and 40% lifetime management and only 20% logic. Furthermore, the logic is hidden in amongst all the other garbage, making even these 11 lines of code very hard to reason about.
It is the first time I am using STL and I am confused about how should I deallocate the the memory used by these containers. For example:
class X {
private:
map<int, int> a;
public:
X();
//some functions
}
Now let us say I define the constructor as:
X::X() {
for(int i=0; i<10; ++i) {
map[i]=i;
}
}
Now my question is should I write the destructor for this class or the default C++ destructor will take care of deallocating the memory(completely)?
Now consider the modification to above class
class X {
private:
map<int, int*> a;
public:
X();
~X();
//some functions
}
Now let us say I define the constructor as:
X::X() {
for(int i=0; i<10; ++i) {
int *k= new int;
map[i]=k;
}
}
Now I understand that for such a class I need to write a destructor as the the memory allocated by new cannot be destructed by the default destructor of map container(as it calls destructor of objects which in this case is a pointer). So I attempt to write the following destructor:
X::~X {
for(int i=0; i<10; ++i) {
delete(map[i]);
}
//to delete the memory occupied by the map.
}
I do not know how to delete the memory occupied by the map. Although clear function is there but it claims to bring down the size of the container to 0 but not necessarily deallocate the memory underneath. Same is the case with vectors too(and I guess other containers in STL but I have not checked them).
Any help appreciated.
should I write the destructor for this class or the default C++ destructor will take care of deallocating the memory(completely)?
Yes it will. All the standard containers follow the principle of RAII, and manage their own dynamic resources. They will automatically free any memory they allocated when they are destroyed.
I do not know how to delete the memory occupied by the map.
You don't. You must delete something if and only if you created it with new. Most objects have their memory allocated and freed automatically.
The map itself is embedded in the X object being destroyed, so it will be destroyed automatically, and its memory will be freed along with the object's, once the destructor has finished.
Any memory allocated by the map is the responsibility of the map; it will deallocate it in its destructor, which is called automatically.
You are only responsible for deleting the dynamically allocated int objects. Since it is difficult to ensure you delete these correctly, you should always use RAII types (such as smart pointers, or the map itself) to manage memory for you. (For example, you have a memory leak in your constructor if a use of new throws an exception; that's easily fixed by storing objects or smart pointers rather than raw pointers.)
When a STL collection is destroyed, the corresponding destructor of the contained object is called.
This means that if you have
class YourObject {
YourObject() { }
~YourObject() { }
}
map<int, YourObject> data;
Then the destructor of YourObject is called.
On the other hand, if you are storing pointers to object like in
map<int, YourObject*> data
Then the destruct of the pointer is called, which releases the pointer itself but without calling the pointed constructor.
The solution is to use something that can hold your object, like a shared_ptr, that is a special object that will care about calling the holded item object when there are no more references to it.
Example:
map<int, shared_ptr<YourObject>>
If you ignore the type of container you're dealing with an just think of it as a container, you'll notice that anything you put in the container is owned by whomever owns the container. This also means that it's up to the owner to delete that memory. Your approach is sufficient to deallocate the memory that you allocated. Because the map object itself is a stack-allocated object, it's destructor will be called automatically.
Alternatively, a best practice for this type of situation is to use shared_ptr or unique_ptr, rather than a raw pointer. These wrapper classes will deallocate the memory for you, automatically.
map<int shared_ptr<int>> a;
See http://en.cppreference.com/w/cpp/memory
The short answer is that the container will normally take care of deleting its contents when the container itself is destroyed.
It does that by destroying the objects in the container. As such, if you wanted to badly enough, you could create a type that mismanaged its memory by allocating memory (e.g., in its ctor) but doesn't release it properly. That should obviously be fixed by correcting the design of those objects though (e.g., adding a dtor that releases the memory they own). Alternatively, you could get the same effect by just storing a raw pointer.
Likewise, you could create an Allocator that didn't work correctly -- that allocated memory but did nothing when asked to release memory.
In every one of these cases, the real answer is "just don't do that".
If you have to write a destructor (or cctor or op=) it indicates you likely do something wrong. If you do it to deallocate a resource more likely so.
The exception is the RAII handler for resources, that does nothing else.
In regular classes you use proper members and base classes, so your dtor has no work of its own.
STL classes all handle themselves, so having a map you have no obligations. Unless you filled it with dumb pointers to allocated memory or something like that -- where the first observation kicks in.
You second X::X() sample is broken in many ways, if exception is thrown on the 5th new you leak the first 4. And if you want to handle that situatuion by hand you end up with mess of a code.
That is all avoided if you use a proper smart thing, like unique_ptr or shared_ptr instead of int*.
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!