Chapter 12 Dynamic Memory
Dynamic Memory and Smart Pointers
shared_ptr,unique_ptrandweak_ptrare smart pointers defined inmemory.- Shared pointers and unique pointers can be used to manage allocated memory for objects:

shared_ptr-specific operations:- It can be initialized with another
shared_ptror anewed pointer:p(q). However, it cannot be implicitly converted from a pointer: direct initialization only (no copy initialization/assignment). - A deleter function can be supplied instead of
deleteat construction:p(q, d). It must take a single argument of a pointer type.qcan be a smart pointer or an address. p.reset(q, d)can be used to move the pointer to another address or smart pointerq.ddefaults todelete, andqdefaults tonullptr.
- It can be initialized with another


- Smart pointers should be initialized with
make_shared<T>(...), which allocates and initializes a dynamic object (arguments are similar toemplace). shared_ptrs keep records of the reference count. When it is destroyed (goes out of range, or gets lost in assignment), the counter will be decremented (in its destructor).- The memory will be released only after the last
shared_ptrgoes away. Be sure to remove unusedshared_ptrelements. shared_ptrs can be used to create dynamic arrays, create dynamic objects and share data between objects (with a pointer member).newcan be used to allocate memory and default/value initialize objects:new string(default),new string()(value).newcan be used withconst:new const int(1024).newcan be used withauto: only a single initializer inside parentheses is accepted. The type will be inferred:new auto(...).newwill throwbad_allocexception if failed. Usingnew (nothrow)(passingnothrowto a placement new, defined innew) will suppress the exception and returnnullptr.
- Do not mix ordinary pointers and smart pointers. This will result in destroying allocated objects by mistake.
- Do not use
getto initialize another smart pointer. This will result in wrong reference counts and destroying by mistake. - Smart pointers can ensure that memory is freed even if the block is exited prematurely (due to exception, etc.).
- Deleter can be used to do post-destruction operations. It can be used in non-dynamic situations:
shared_ptr<T> p(&c, end)will callendat the end of the function (cis local). unique_ptr-specific operations:- A
unique_ptrshould always be initialized withnullptror anewed pointer. It does not support ordinary copy or assignment (p.reset(...)only). The only exception is returning aunique_ptrfrom a function, in which a special copy will be created. p.release()does not free the memory; it only breaks the connection between theunique_ptrand the object.- Unlike
shared_ptr, the type of the deleter is part of the type and should be supplied in the angle brackets:unique_ptr<objT, delT> p (new objT, fcn). It is called when theunique_ptris destroyed.
- A

weak_ptrdoes not impact the lifetime of the object.weak_ptr-specific operations:wp.lock()is used to check if the pointer is valid.

Dynamic Arrays
newcan be used with type aliases of array types.
typedef int arrT[42];
int *p = new arrT;
begin()andend()cannot be used on dynamic arrays: they use the array dimension to return pointers. Similarly, rangefors cannot be used to process a dynamic array.- Objects are default initialized by default. They are value initialized if followed by an empty pair of parentheses. A braced list of initializers is also supported. A single element initializer is not allowed for dynamic arrays (
autonot supported). new int[0]will return a valid, nonzero pointer. No special cases are necessary.- Elements in an array are destroyed in reverse order.
- A special version of
unique_ptrcan be used on arrays allocated bynew(with a deleter). However,shared_ptrcan only be used as an ordinary pointer with a customized deleter.

allocator(defined inmemory) decouples allocation from construction. There is no need to initialize a large buffer of objects ahead of input and let most of them go to waste.- The allocated memory is unconstructed. We need to use a pointer to somewhere in that memory to
constructan element at that location, anddestroyit after use.
- The allocated memory is unconstructed. We need to use a pointer to somewhere in that memory to

allocator<string> alloc; // object that can allocate strings
auto const p = alloc.allocate(n); // allocate n unconstructed strings
auto q = p; // q will point to one past the last constructed element
alloc.construct(q++); // *q is the empty string
alloc.construct(q++, 10, 'c'); // *q is cccccccccc
while (q != p)
alloc.destroy(--q); // destroy the strings we actually allocated
alloc.deallocate(p, n); // free the allocated memory
- The allocated memory can be managed with library algorithms defined in
memory:- All these functions take iterators or pointers as parameters.
unitialized_copyreturns the incremented destination iterator likecopy.
