Last active
March 14, 2020 12:32
-
-
Save janderudder/13562bd1fd262e35635f4cb6559de53f to your computer and use it in GitHub Desktop.
unique_ptr as parameter : difference between taking by value or by rvalue reference
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <memory> | |
/** | |
* Sample types with loud destructors | |
*/ | |
struct By_value | |
{ | |
int i; | |
By_value(int ai) : i{ai} {}; | |
~By_value() { | |
std::cout << "=> 'taken by value' (" << i << ") is now destructed\n"; | |
} | |
}; | |
struct By_rvalue_reference | |
{ | |
int i; | |
By_rvalue_reference(int ai) : i{ai} {}; | |
~By_rvalue_reference() { | |
std::cout << "=> 'taken by rvalue reference' (" << i << ") is now destructed\n"; | |
} | |
}; | |
/** | |
* Taking by rvalue ref enables us to steal the ownership or to leave the | |
* client's unique_ptr untouched. | |
*/ | |
void get_value(std::unique_ptr<By_rvalue_reference>&& p, bool steal) | |
{ | |
std::cout << "inside get_value(std::unique_ptr&&)\n"; | |
if (steal) { | |
static auto stolen_ptr = std::move(p); | |
std::cout << "ownership has been stolen\n"; | |
} | |
std::cout << "leaving the function\n"; | |
} | |
/** | |
* Taking by value calls the move constructor immediately, which means the | |
* object is moved from client-site whatever happens in the functions. | |
* If we don't store it, it is destroyed at the end of function scope. | |
*/ | |
void get_value(std::unique_ptr<By_value> p, bool steal) | |
{ | |
std::cout << "inside get_value(std::unique_ptr)\n"; | |
if (steal) { | |
static auto stolen_ptr = std::move(p); | |
std::cout << "ownership has been stolen\n"; | |
} | |
std::cout << "leaving the function\n"; | |
} | |
int main() | |
{ | |
auto by_val_a = std::make_unique<By_value>(1); | |
auto by_val_b = std::make_unique<By_value>(2); | |
auto by_rval_ref_a = std::make_unique<By_rvalue_reference>(3); | |
auto by_rval_ref_b = std::make_unique<By_rvalue_reference>(4); | |
constexpr bool steal = true; | |
constexpr bool dont_steal = false; | |
get_value(std::move(by_val_a), steal); std::cout << "\n"; | |
get_value(std::move(by_rval_ref_a), steal); std::cout << "\n"; | |
get_value(std::move(by_val_b), dont_steal); std::cout << "\n"; | |
get_value(std::move(by_rval_ref_b), dont_steal); std::cout << "\n"; | |
std::cout << "leaving main\n\n"; | |
} | |
/* Program output: | |
inside get_value(std::unique_ptr) | |
ownership has been stolen | |
leaving the function | |
inside get_value(std::unique_ptr&&) | |
ownership has been stolen | |
leaving the function | |
inside get_value(std::unique_ptr) | |
leaving the function | |
=> 'taken by value' (2) is now destructed | |
inside get_value(std::unique_ptr&&) | |
leaving the function | |
leaving main | |
=> 'taken by rvalue reference' (4) is now destructed | |
=> 'taken by rvalue reference' (3) is now destructed | |
=> 'taken by value' (1) is now destructed | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment