Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is going on: C++ std::move on std::shared_ptr increases use_count?

I was always assuming that std::move() on a std::shared_ptr steals the pointer and sets the pointer of the original to nullptr-thus not increasing the reference count. That does not seem to be true in my world.

SETUP:

MacOS, g++ -version => "Apple LLVM version 10.0.1 (clang-1001.0.46.3)"

CODE:

#include <cstdio>                                                                                                                                                                                   #include <memory> class Thing { public: Thing(int N) : value(N) {} int value; };  void print(const char* name, std::shared_ptr<Thing>& sp) { printf("%s: { use_count=%i; }\n", name, (int)sp.use_count()); }  int main(int argc, char** argv) {     std::shared_ptr<Thing>  x(new Thing(4711));     print("BEFORE x", x);     std::shared_ptr<Thing>  y = std::move(x);     y->value = 4712;     print(" AFTER x", x);     print(" AFTER y", y);     return 0; } 

OUTPUT:

Compiling (g++ tmp.cpp -o test), and running (./test), delivers

BEFORE x: { use_count=1; }  AFTER x: { use_count=2; }  AFTER y: { use_count=2; } 

So, the reference count is increased while using std::move().

QUESTION:

What is going on, here?

like image 434
Frank-Rene Schäfer Avatar asked Sep 09 '19 10:09

Frank-Rene Schäfer


People also ask

What happens if you move a shared_ptr?

By moving the shared_ptr instead of copying it, we "steal" the atomic reference count and we nullify the other shared_ptr . "stealing" the reference count is not atomic, and it is hundred times faster than copying the shared_ptr (and causing atomic reference increment or decrement).

What is the std :: move is doing?

std::move. std::move is used to indicate that an object t may be "moved from", i.e. allowing the efficient transfer of resources from t to another object. In particular, std::move produces an xvalue expression that identifies its argument t . It is exactly equivalent to a static_cast to an rvalue reference type.

What does shared_ptr get () do?

std::shared_ptr::getReturns the stored pointer. The stored pointer points to the object the shared_ptr object dereferences to, which is generally the same as its owned pointer.

How does STD move work C++?

In C++11, std::move is a standard library function that casts (using static_cast) its argument into an r-value reference, so that move semantics can be invoked. Thus, we can use std::move to cast an l-value into a type that will prefer being moved over being copied.


Video Answer


1 Answers

What is going on, here?

On MacOS, it seems that you must explicitly enable move-sematics with -std=c++11 (or later standards)¹. Otherwise, the example happens to compile (i.e., std::shared_ptr from the related library implementation is usable) but doesn't work correctly as the required language features aren't enabled. This results in actual copies being made instead of move constructions. It would have been better if the AppleClang package didn't even allow an instantiation of std::shared_ptr when the required language features isn't enabled.

¹) Thanks to @t.niese for testing the given compiler/platform.

like image 131
lubgr Avatar answered Sep 18 '22 14:09

lubgr