Pageviews

Wednesday, July 22, 2015

unique_ptr vs shared_ptr (weak_ptr) vs auto_ptr

unique_ptr

In C++, a smart pointer is implemented as a template class that mimics, by means of operator overloading, the behaviors of a traditional (raw) pointer, (e.g. dereferencing, assignment) while providing additional memory management features.
Smart pointers can facilitate intentional programming by expressing in the type itself how the memory of the referent of the pointer will be managed. For example, if a C++ function returns a pointer, there is no way to know whether the caller should delete the memory of the referent when the caller is finished with the information.
some_type* ambiguous_function(); // What should be done with the result?
Traditionally, comments have been used to resolve the ambiguity[citation needed], which is an error-prone, labor-intensive approach. C++11 introduced a way to ensure correct memory management in this case by declaring the function to return a unique_ptr,
unique_ptr<some_type> obvious_function1();
The declaration of the function return type as a unique_ptr makes explicit the fact that the caller takes ownership of the result, and the C++ runtime ensures that the memory for *some_type will be reclaimed automatically. Prior toC++11, unique_ptr can be replaced with auto_ptr.
Example: unique_ptr can only be transferred not copied.
std::unique_ptr<int> p1(new int(5));
std::unique_ptr<int> p2 = p1; //Compile error.
std::unique_ptr<int> p3 = std::move(p1); //Transfers ownership. p3 now owns the memory and p1 is rendered invalid.

p3.reset(); //Deletes the memory.
p1.reset(); //Does nothing.

shared_ptr (weak_ptr)
shared_ptr is a container for a raw pointer. It maintains reference-counted ownership of its contained pointer in cooperation with all copies of the shared_ptr. The object referenced by the contained raw pointer will be destroyed when and only when all copies of the shared_ptr have been destroyed.
std::shared_ptr<int> p1(new int(5));
std::shared_ptr<int> p2 = p1; //Both now own the memory.

p1.reset(); //Memory still exists, due to p2.
p2.reset(); //Deletes the memory, since no one else owns the memory.
weak_ptr is a container for a raw pointer. It is created as a copy of a shared_ptr. The existence or destruction of weak_ptr copies of a shared_ptr have no effect on the shared_ptr or its other copies. After all copies of a shared_ptr have been destroyed, all weak_ptr copies become empty.
Because the implementation of shared_ptr uses reference countingcircular references are potentially a problem. A circular shared_ptr chain can be broken by changing the code so that one of the references is aweak_ptr.
Multiple threads can safely simultaneously access different shared_ptr and weak_ptr objects that point to the same object.[4]
The referenced object itself needs to be protected separately to ensure thread safety.

auto_ptr 
Create new objects using auto_ptr to ease the allocation of a
std::shared_ptr<some_type>
C++11 introduced:
 auto s = std::make_shared<some_type>(constructor, parameters, here);
and similarly
std::unique_ptr<some_type>
Since C++14 one can use:
 auto u = std::make_unique<some_type>(constructor, parameters, here);
It is preferred, in almost all circumstances, to use these facilities over the new keyword:[1]

stdcall vs cdecl

The _stdcall calling convention is a variation on the Pascal calling convention in which the callee is responsible for cleaning up the stack, so the compiler makes vararg functions__cdecl. 
stdcall is the standard calling convention for the Microsoft Win32 API and for Open Watcom C++.
Element
Implementation
Argument-passing order
Right to left.
Argument-passing convention
By value, unless a pointer or reference type is passed.
Stack-maintenance responsibility
Callee pops its own arguments from the stack.
Name-decoration convention
An underscore (_) is prefixed to the name. The name is followed 
by the at sign (@) followed by the number of bytes (in decimal) 
in the argument list. Therefore, the function declared as
int func( int a, double b ) is decorated as follows: _func@12
Case-translation convention
No case translation performed.

The _cdecl calling convention is the default calling convention for C and C++ programs. Because the stack is cleaned up by the caller, it can do vararg functions.  Registers EAX, ECX, and EDX are designated for use within the function. Return values are stored in the EAX register.
Element
Implementation
Argument-passing order
Right to left.
Stack-maintenance responsibility
Caller pops the arguments from the stack.
Name-decoration convention
Underscore character (_) is prefixed to names, except 
when __cdecl functions that use C linkage are exported.
Case-translation convention
No case translation performed.
Subtle differences
The __cdecl calling convention creates larger executables than __stdcall, because it requires each function call to include stack cleanup code.