1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
|
hi(placement new: generic algorithms)hi(uninitialized... algorithms)
Section ref(PLACEMENT) covers the placement new operator. The placement new
operator is used to install values or objects in 'raw memory', i.e., memory
that is already available, but hasn't yet been initialized for the intended
object types.
As covered before, when calling something like tt(auto ptr = new string{
"hello" }) the string is constructed in memory specifically allocated to
contain the object, and the object type's constructor initializes the object
in that memory. Likewise, when calling tt(delete ptr) the string's destructor
is called, followed by returning the memory allocated by tt(new) to the common
pool.
When using placement new the memory to contain the object is already
available, and the construction tt(auto ptr = new (storageAddress) string{
"hello" }) is used to merely construct the string at the location specified by
tt(storageAddress). That string can then (as usual) be accessed via tt(ptr),
but tt(delete ptr) cannot be used, since the memory at tt(storageAddress) was
already available before invoking the placement new operator. Therefore, in
these cases the remarkable situation is encountered where the object's
destructor must explicitly be called (using tt(ptr->~string())) and using
tt(delete ptr) is completely wrong, causing a memory error which aborts the
program.
Several generic algorithms, all supporting execution policies, are available
simplifying the use of tt(placement new). To use these algorithm the
tthi(memory) header file must be included.
Facilities are available to copy, fill, initialize, and move objects to/in
uninitialized (raw) memory, as well as facilities to delete the objects stored
in raw memory. Here is an overvieuw of the available facilities (cf.
url(cppreference)(https://en.cppreference.com) for more details
about the algorithms handling uninitialized memory):
itemization(
itt(uninitialized_copy([ExecPol,]
ForwardIterator first, ForwardIterator last,
ForwardIterator dest);)nl()
copies the elements in the rangett(first, last) to the raw memory
starting at tt(dest), returning the location beyond the last copied
element.
itt(uninitialized_copy_n([ExecPol,]
ForwardIterator first, size_t nObjects,
ForwardIterator dest);)nl()
same as the previous algorithm, but copies tt(nObjects).
itt(uninitialized_default_construct([ExecPol,]
ForwardIterator first, ForwardIterator last);)nl()
installs default constructed values at the raw memory locations reached
by the iterator range rangett(first, last). The algorithm requires
that the types referred to by the iterators are either trivial types
(like built-in types) or define tt(value_type) returning their type
names. When using trivial types the installed do not assume that the
installed values are 0-initialized.
itt(uninitialized_default_construct_n([ExecPol,]
ForwardIterator first, size_t nObjects);)nl()
same as the previous algorithm, but installs tt(nObjects) in the
uninitialized memory.
itt(uninitialized_fill([ExecPol,]
ForwardIterator first, ForwardIterator last,
Type const &value);)nl()
like the first algorithm, but installing copies of tt(value) in the
uninitialized memory.
itt(uninitialized_fill([ExecPol,]
ForwardIterator first, size_t nObjects,Type const &value);)nl()
same as the previous algorithm, but copies tt(value) to the
tt(nObjects) subsequent locations in the uninitialized memory.
itt( uninitialized_move([ExecPol,]
ForwardIterator first, ForwardIterator last,
ForwardIterator dest);)nl()
same as the first algorithm, but the elements in the rangett(first,
last) are moved to the raw memory.
itt(uninitialized_move_n([ExecPol,]
ForwardIterator first, size_t nObjects,
ForwardIterator dest);)nl()
same as the previous algorithm, but tt(nObjects) are moved.
itt(uninitialized_value_construct([ExecPol,]
ForwardIterator first, ForwardIterator last);)nl()
same as tt(uninitialized_default_construct), but requires that the
types referred to by the iterators define tt(value_type) returning
their type names.
itt(uninitialized_value_construct_n([ExecPol,]
ForwardIterator first, size_t nObjects);)nl()
same as the previous algorithm, but installs tt(nObjects) in the
uninitialized memory.
)
The algorithm hi(construct_at) tt(Type *construct_at(Type *raw, Args
&&...args)) constructs an object of type tt(Type) in the raw memory at
tt(raw), passing tt(args...) to tt(Type's) constructor.
To delete the objects installed in raw memory the following facilities are
available:
itemization(
itt(void destroy([ExecPol,] ForwardIterator first,
ForwardIterator last);)nl()
assuming the the types to which tt(first) refers: it calls
tt(iterator->~Type()) for all elements in the range rangett(first,
last).
itt(void destroy([ExecPol,] ForwardIterator first, size_t nObjects);)nl()
same as the previous algorithm, but calls the destructors of
tt(nObjects) objects.
itt(void destroy_at(Type *raw);)nl()
calls the destructor of the object installed at tt(raw) using placement
new. If the tt(raw) pointer points to an array of placement new
allocated objects then the destructors of the elements of the array
are called.
)
Here is an example:
verbinclude(-as4 examples/uninitialized.cc)
|