Memory allocation: Difference between revisions

Content deleted Content added
omit Ruby
Ce (talk | contribs)
→‎C++: Added content
Line 127: Line 127:
}</lang>
}</lang>


==C++==
=={{header|C++}}==
While the C allocation functions are also available in C++, their use is discouraged. Instead, C++ provides <code>new</code> and <code>delete</code> for memory allocation and deallocation. Those function don't just allocate memory, but also initialize objects. Also, deallocation is coupled with destruction.
'''TODO:''' new and delete/delete[]
<lang cpp>
#include <string>

int main()
{
int* p;

p = new int; // allocate a single int, uninitialized
delete p; // deallocate it

p = new int(2); // allocate a single int, initialized with 2
delete p; // deallocate it

std::string p2;

p2 = new std::string; // allocate a single string, default-initialized
delete p2; // deallocate it

p = new int[10]; // allocate an array of 10 ints, uninitialized
delete[] p; // deallocation of arrays must use delete[]

p2 = new std::string[10]; // allocate an array of 10 strings, default-initialized
delete[] p2; // deallocate it
}
</lang>
Note that memory allocated with C allocation functions (<code>malloc</code>, <code>calloc</code>, <coderealloc</code>) must always be deallocated with <code>free</code>, memory allocated with non-array <code>new</code> must always be deallocated with <code>delete</code>, and memory allocated with array <code>new</code> must always deallocated with <code>delete[]</code>. Memory allocated with new also cannot be resized with <code>realloc</code>.

Note that use of the array form is seldom a good idea; in most cases, using a standard container (esp. <code>std::vector</code>) is a better idea, because it manages the memory for you, it allows you to define an initial value to set in the array (new[] always default-initializes), and like malloc, but unlike array new, it allows resizing (and unlike realloc, it correctly handles construction/destruction when resizing).

Besides the new expressions shown above, pure memory allocation/deallocation without object initialization/destruction can also be done through <code>operator new</code>:
<lang cpp>
int main()
{
void* memory = operator new(20); // allocate 20 bytes of memory
operator delete(memory); // deallocate it
}
</lang>

There's also a placement form of new, which allows to construct objects at an arbitrary adress (provided it is correctly aligned, and there's enough memory):
<lang cpp>
#include <new>

int main()
{
union
{
int alignment_dummy; // make sure the block is correctly aligned for ints
char data[2*sizeof(int)]; // enough space for 10 ints
};
int* p = new(&data) int(3); // construct an int at the beginning of data
new(p+1) int(5); // construct another int directly following
}
</lang>
Indeed, code like <code>int* p = new int(3);</code> is roughly (but not exactly) equivalent to the following sequence:
<lang cpp>
void* memory_for_p = operator new(sizeof(int));
int* p = new(memory_for_p) int(3);
</lang>

Normally, new throws an exception if the allocation fails. there's a non-throwing variant which returns a null pointer instead:
<lang cpp>
#include <new>

int* p = new(std::nothrow) int(3);
</lang>
Note that the nothrow variant does <em>not</em> prevent any exceptions to be thrown from the constructor of an object created with new. It only prevents exceptions due to memory allocation failure.

It is also possible to implement user-defined variations of operator new. One possibility is to define class-based operator new/operator delete:
<lang cpp>
#include <cstddef>
#include <cstdlib>
#include <new>

class MyClass
{
public:
void* operator new(std::size_t size)
{
void* p = std::malloc(size);
if (!p) throw std::bad_alloc();
return p;
}
void operator delete(void* p)
{
free(p);
}
};

int main()
{
MyClass* p = new MyClass; // uses class specific operator new
delete p; // uses class specific operator delete

int* p2 = new int; // uses default operator new
delete p2; // uses default operator delete
}
</lang>

Another possibility is to define new arguments for placement new syntax, e.g.
<lang cpp>
class arena { /* ... */ };

void* operator new(std::size_t size, arena& a)
{
return arena.alloc(size);
}

void operator delete(void* p, arena& a)
{
arena.dealloc(p);
}

arena whatever(/* ... */);

int* p = new(whatever) int(3); // uses operator new from above to allocate from the arena whatever
</lang>
Note that there is ''no'' placement delete syntax; the placement operator delete is invoked by the compiler only in case the constructor of the newed object throws. Therefore for placement newed object deletion the two steps must be done explicitly:
<lang cpp>
class MyClass { /*...*/ };

int main()
{
MyClass* p = new(whatever) MyClass; // allocate memory for myclass from arena and construct a MyClass object there
// ...
p->~MyClass(); // explicitly destruct *p
operator delete(p, whatever); // explicitly deallocate the memory
}
</lang>


=={{header|E}}==
=={{header|E}}==