5
std::shared_ptr<std::string> test() {
  return std::make_shared<std::string>("sdsd");
}
cout << *test() << endl;

The above code works. Can someone please let me know where is the "sdsd" string stored. I was expecting it to error out as rvalue is a temporary object. Where is the rvalue copied to and stored in?

With weak_ptr

std::weak_ptr<std::string> test() {
  return std::make_shared<std::string>("sdsd");
}
  cout << *test().lock() << endl;

Interestingly the above code errors out. What's the difference?

claudius
  • 1,112
  • 1
  • 10
  • 23
  • 1
    yeah I am new to C++. – claudius Apr 13 '22 at 03:21
  • 1
    Thanks I am working my way through tour of C++ and https://en.cppreference.com/. Can you please help me understand where rvalue shared_ptr are stored? – claudius Apr 13 '22 at 03:25
  • 1
    I have also reduced the scope of the question to make it easy to answer. – claudius Apr 13 '22 at 03:28
  • 2
    The literal answer to your question is the semantics of a `weak_ptr` is different: it doesn't count as a reference. That's the whole point of `weak_ptr`. – Passer By Apr 13 '22 at 03:32
  • In the second version, the destruction of the temporary `shared_ptr` means there are zero references to the stored string, so it is released. In the first version there is still one reference , the return value – M.M Apr 13 '22 at 03:38
  • After returning from `test()` you get a temporary object. Normally its lifetime (https://en.cppreference.com/w/cpp/language/lifetime) ends after evaluating the expression. '*All temporary objects are destroyed as the last step in evaluating the full-expression that (lexically) contains the point where they were created*'. Assign the result of `test()` to a variable to make lifetime more clear. In the second example the `shared_ptr` was passed to a `weak_ptr`, which does not count, when counting the number of active usages of the object and, when leaving `test()`, the usage counter goes to `0`. – Sebastian Apr 13 '22 at 05:58

2 Answers2

6

In

std::shared_ptr<std::string> test() {
  return std::make_shared<std::string>("sdsd");
}

the constructed shared_ptr is returned and lives on as a temporary variable long enough to be used by the caller before going out of scope and freeing the string allocated by make_shared.

The "sdsd" string is stored in dynamic storage owned by the returned shared_ptr.

In

std::weak_ptr<std::string> test() {
  return std::make_shared<std::string>("sdsd");
} 

the shared_ptr wasn't returned and went out of scope, taking the string allocated by make_shared with it. Since this was the only existing copy of the shared_ptr this leaves the returned temporary weak_ptr variable connected to an expired share_ptr. If you test the return value of lock you'll see it's a default-constructed shared_ptr holding a null pointer.

Documentation for std::weak_ptr::lock.

The "sdsd" string isn't stored anywhere after test returns. It departed when the shared_ptr that owned it went out of scope.

user4581301
  • 33,082
  • 7
  • 33
  • 54
1

The above code works. Can someone please let me know where is the "sdsd" string stored. I was expecting it to error out as rvalue is a temporary object. Where is the rvalue copied to and stored in?

The memory was allocated in the call to make_shared.

Interestingly the above code errors out. What's the difference?

The difference is that the lock operation on a weak_ptr can fail if there does not exist at least one shared_ptr to the object. That's the purpose of weak_ptr -- to allow the object to be freed and access it only if it still exists.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278