Assume that ITEM is a class
ITEM* items = new ITEM[10];
for(i=0;i<10;++i)
new(&items[i)ITEM();
new(&items[0])ITEM(items[1]);
Is the above valid?
The way I understand it is that the last 2 uses of the new operator
do not allocate memory. They just invoke the constructor of ITEM.
Is the above equivalent to?
ITEM* items = new ITEM[10];
for(i=0;i<10;++i)
items[i] = ITEM();
item[0] = ITEM(items[1]);
EDIT:
https://github.com/gosom/practice-cpp/blob/master/arrays/darray.h
I use it here (for practicing)
The way I understand it is that the last 2 uses of the new operator do not allocate memory. They just invoke the constructor of ITEM.
Yes. This is the "placement new" operator, wich does not allocate memory and calls object constructor. This is legal to proceed the way you do, though ITEM constructor will be called twice (meaning that the ITEM class constructor will be executed twice: one when standard new is called, one when placement new is called). This may lead to memory leak (or other unexpected behavior) if some ressources are allocated in ITEM's constructor. See this for more info about placement new.
Is the above equivalent to?
No, this is not equivalent. In the latter case, you create a temporary object at each loop, which you copy to item[i]. This will call ITEM constructor, assignment operator, and destructor, at each loop. In the previous situation, placement new only calls ITEM constructor, nothing else.
The typical usage of "placement new" is when you want your object to be allocated in a specific memory area (instead of the heap, where standard new operator allocates memory). This may be shared memory or so... "Placement new" is one of the few situations where the object destructor can/must be called explicitely, i.e.: item[i]->~ITEM()
for(i=0;i<10;++i)
new(&items[i)ITEM();
The above is potentially invalid. The new operator constructs each object in the array already. This is double construction (which can and probably will lead to errors for less than trivial types).
for(i=0;i<10;++i)
items[i] = ITEM();
This just assigns a default constructed object to each entry in the array. This is as safe as the assignment operator is.
In general placement new is supposed to be used on raw memory.
Related
I am writing a template class which internally manages an array of the given type. Like this:
template<typename T>
class Example {
// ...
private:
T* objects; // allocated in c'tor (array), deleted in d'tor
// ...
};
I was wondering if C++ calls the destructor of each object in objects when I delete it via delete[] objects;.
I need to know this, because the objects in my class do not contain sensible values all the time, so the destructors should not be called when they don't.
Additionally, I'd like to know if the destructors would be called if I declared a fixed-sized array like T objects[100] as part of Example<T>.
If T has a destructor then it will be invoked by delete[]. From section 5.3.5 Delete of the c++11 standard (draft n3337), clause 6:
If the value of the operand of the delete-expression is not a null pointer value, the delete-expression will
invoke the destructor (if any) for the object or the elements of the array being deleted. In the case of an
array, the elements will be destroyed in order of decreasing address (that is, in reverse order of the completion
of their constructor; see 12.6.2).
The destructor for a type T will also be invoked for each element in an array of T[] when the array is not dynamically allocated and array goes out of scope (lifetime ends).
I need to know this, because the objects in my class do not contain sensible values all the time, so the destructors should not be called when they don't.
But, there seems to be a very significant problem with an object that can acquire a state where it cannot be destructed.
Yes, the destructor will be called for all objects in the array when using delete[]. But that shouldn't be an issue, since the constructor was called for all objects in the array when you used new[] (you did, right ?) to allocate it.
If a constructed object can be in such a state that calling the destructor would be invalid, then there's something seriously wrong with your object. You need to make your destructor work in all cases.
delete [] does call the destructor for each element of the array. Same happens for a member array (your T objects[100]).
You want to keep it as pointer, and design the destructor (and copy constructor, and copy assignment operator, see rule of three/five) for your template to deal with "non-sensible" values pointed to by objects.
The answer is yes. Destructor for each object is called.
On a related note, you should try to avoid using delete whenever possible. Use smart pointers (e.g.,unique_ptr, shared_ptr) and STL containers (e.g., std::vector, std::array) instead.
delete[] objects is similar (but not identical) to:
for (i = 0; i < num_of_objects; ++i) {
delete objects[i];
}
since delete calls the destructor, you can expect delete[] to do the same.
Yes, delete[] guarantees destructors are called on every object.
Depending on your use case, using Boost pointer containers, or simply containers of smart pointers, might make it a lot easier to have (exception safe) collection of pointers.
Say I have the following code in a C++ program:
Object a = Object(someParameters);
new (&a) Object(someOtherParameters);
My assumption is that it replaces the contents of a with Object(someOtherParameters), avoiding a possible operator= declared for Object. Is this correct?
It's called placement new. It calles the constructor on the specified memory rather than allocating new memory. Note that in this case you have to explicitly call the destructor of your object before freeing the allocated memory.
Clarification. Suppose you have allocated some raw memory
char * rawMemory = new char [sizeof (Object)];
and you want to construct an object on that memory. You call
new(rawMemory) Object(params);
Now, before freeing the memory
delete [] rawMemory;
you will have to call the derstuctor of Object explicitly
reinterpret_cast<Object*>(rawMemory)->~Object();
In your particular example, however, the potential problem is that you haven't properly destroyed the existing object before constructing a new one in its memory.
Bonus:
Ever wondered how standard std::vector can do without its contained objects being default-constructible? The reason is that on most, if not all, implementations allocator<T> does not store a T* p which would require T to be default-constructible in case of p = new T[N]. Instead it stores a char pointer - raw memory, and allocates p = new char[N*sizeof(T)]. When you push_back an object, it just calls the copy constructor with placement new on the appropriate address in that char array.
It's known as placement new: it constructs the new Object at the address given inside the parentheses. Placement new is usually used to create an object in raw memory. Constructing a new object on top of an existing one, as this code does, is a bad idea, because it doesn't call the destructor on the original object.
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!
Assume you have an object of class Fool.
class Fool
{
int a,b,c;
double* array ;
//...
~Fool()
{
// destroys the array..
delete[] array ;
}
};
Fool *fool = new Fool() ;
Now, I know you shouldn't, but some fool calls the destructor on fool anyway. fool->~Fool();.
Does that mean fool's memory is freed, (ie a,b,c are invalid) or does that mean only whatever deallocations in ~Fool() function occur (ie the array is deleted only?)
So I guess my question is, is a destructor just another function that gets called when delete is called on an object, or does it do more?
If you write
fool->~Fool();
You end the object's lifetime, which invokes the destructor and reclaims the inner array array. The memory holding the object is not freed, however, which means that if you want to bring the object back to life using placement new:
new (fool) Fool;
you can do so.
According to the spec, reading or writing the values of the fields of fool after you explicitly invoke the destructor results in undefined behavior because the object's lifetime has ended, but the memory holding the object should still be allocated and you will need to free it by invoking operator delete:
fool->~Fool();
operator delete(fool);
The reason to use operator delete instead of just writing
delete fool;
is that the latter has undefined behavior, because fool's lifetime has already ended. Using the raw deallocation routine operator delete ensures that the memory is reclaimed without trying to do anything to end the object's lifetime.
Of course, if the memory for the object didn't come from new (perhaps it's stack-allocated, or perhaps you're using a custom allocator), then you shouldn't use operator delete to free it. If you did, you'd end up with undefined behavior (again!). This seems to be a recurring theme in this question. :-)
Hope this helps!
The destructor call does just that, it calls the destructor. Nothing more and nothing less. Allocation is separate from construction, and deallocation from destruction.
The typical sequence is this:
1. Allocate memory
2. Construct object
3. Destroy object (assuming no exception during construction)
4. Deallocate memory
In fact, if you run this manually, you will have to call the destructor yourself:
void * addr = ::operator new(sizeof(Fool));
Fool * fp = new (addr) Fool;
fp->~Fool();
::operator delete(addr);
The automatic way of writing this is of course Fool * fp = new Fool; delete fp;. The new expression invokes allocation and construction for you, and the delete expression calls the destructor and deallocates the memory.
Does that mean fool's memory is freed, (ie a,b,c are invalid) or does
that mean only whatever deallocations in ~Fool() function occur (ie
the array is deleted only?)
Fool::~Fool() has zero knowledge about whether the Fool instance is stored in dynamic storage (via new) or whether it is stored in automatic storage (i.e. stack objects). Since the object ceases to exist after the destructor is run, you can't assume that a, b, c and array will stay valid after the destructor exits.
However, because Fool::~Fool() knows nothing about how the Fool was allocated, calling the destructor directly on a new-allocated Fool will not free the underlying memory that backs the object.
You should not access a, b, and c after the destructor is called, even if it's an explicit destructor call. You never know what your compiler puts in your destructor that might make those values invalid.
However, the memory is not actually freed in the case of an explicit destructor call. This is by design; it allows an object constructed using placement new to be cleaned up.
Example:
char buf[sizeof (Fool)];
Fool* fool = new (buf) Fool; // fool points to buf
// ...
fool->~Fool();
The easiest place to see that the destructor is distinct from deallocation via delete is when the allocation is automatic in the first place:
{
Fool fool;
// ~Fool called on exit from block; nary a sign of new or delete
}
Note also the STL containers make full use of the explicit destructor call. For example, a std::vector<> treats storage and contained objects lifetime quite separately.
In the use of "placement new" it is suggested to call the constructor and destructor explicitly.
In this case will the objects initialized in the initializer section of a class also get properly constructed?
Same too with explicitly calling the destructor? Do the member objects get destroyed properly?
In the use of "placement new" it is
suggested to call the constructor and
destructor explicitly.
It's not correct to say that "you call constructor explicitly", as constructors don't have names ($12.1/1).
In this case will the objects
initialized in the initializer section
of a class also get properly
constructed?
Yes. Why do you doubt it? Placment new only means that the new operator will not allocate any memory, rather will use the memory which you pass in placement new, to construct the object. The object gets constructed in the memory which you pass.
Same too with explicitly calling the
destructor? Do the member objects get
destroyed properly?
Yes.
In the use of "placement new" it is suggested to call the constructor and destructor explicitly.
I don't think so. It will say that you need to call the destructor explicitly.
In this case will the objects initialized in the initializer section of a class also get properly constructed?
Apart from the supplying of the memory all other aspects of placement new are the same as normal new. So rather than dynamically allocating memory it just uses the supplied pointer.
Same too with explicitly calling the destructor?
You can (if you feel naught) call the destructor explicitly on any object. It will call the user defined (or compiler generated) class destructor as normal. The reason you need to explicitly do it for objects created via placement new is that you can call delete on these objects. This is because delete assumes the object was created in dynamically allocated memory and tries to re-cycle that memory after the destructor has been called.
Do the member objects get destroyed properly?
Yes.
If we think of new like this:
// not real code
template<class T> T* new(void* location = NULL) (ArgumentsForT)
{
// If you do not provide location (normal usage)
// then we allocate some memory for you.
if (location == NULL)
{ location = malloc(sizeof(T)); // Use of malloc() is just an example
}
((T*)location)->Constructor(ArgumentsForT);
return (T*)location;
}
So placement new will work just like normal new.
Looking at the call to delete
template<typename T> void delete(T* obj)
{
if (obj != NULL)
{
obj->~T();
free(obj);
}
}
The trouble here is that delete can not tell if the memory was allocated by new or if the memory was allocated by the user and passed into new (placement new). So it always calls free on the memory. If you used placement new then you may not have dynamically allocated the memory (or the memory is still being used for something else).
char x[sizeof(T)]; // don't do this (memory may not be aligned correctly).
T* obj = new (x) T();
delete obj; // FAIL. The memory was not dynamically allocated.
// Delete will try and re-claim this memory for re-yse
// Even if the memory is local.
// This is why on placement new you need to call the destructor
obj->~T();