Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is difference between "owned pointer" and the "stored pointer" for std::shared_ptr?

As per this documentation, which says (emphasis mine):

http://www.cplusplus.com/reference/memory/shared_ptr/owner_before/

Unlike the operator< overload, this ordering takes into consideration the shared_ptr's owned pointer, and not the stored pointer in such a way that two of these objects are considered equivalent (i.e., this function returns false no matter the order of the operands) if they both share ownership, or they are both empty, even if their stored pointer value are different.

The stored pointer (i.e., the pointer the shared_ptr object dereferences to) may not be the owned pointer (i.e., the pointer deleted on object destruction) if the shared_ptr object is an alias (alias-constructed objects and their copies).

What is the difference between "owned pointer" and the "stored pointer" of std::shared_ptr?

I would be grateful to have some help with this question.

Here is some related code (check http://cpp.sh/27auqq):

// enable_shared_from_this example
#include <iostream>
#include <memory>

struct C : std::enable_shared_from_this<C> {int a; int b; };

int main () {
  std::shared_ptr<C> foo, bar;

  foo = std::make_shared<C>();

  bar = foo->shared_from_this();
  
  std::shared_ptr<int> p1(foo, &foo->a);
  std::shared_ptr<int> p2(foo, &foo->b);
  
  *p1=5;
  *p2=9;
  
  std::cout << p1.use_count() << std::endl;
  std::cout << foo->a << std::endl;
  std::cout << foo->b << std::endl;

  if (!foo.owner_before(bar) && !bar.owner_before(foo))
    std::cout << "foo and bar share ownership" << std::endl;
    
  if(!p1.owner_before(p2) && !p2.owner_before(p1))
    std::cout << "p1 and p2 share ownership" << std::endl;
    
    if(!p1.owner_before(foo) && !foo.owner_before(p1))
    std::cout << "p1 and foo share ownership" << std::endl;
      

  return 0;
}

Here is the output:

4
5
9
foo and bar share ownership
p1 and p2 share ownership
p1 and foo share ownership
like image 608
John Avatar asked Jun 09 '20 05:06

John


People also ask

Who owns a shared_ptr?

shared_ptr objects can only share ownership by copying their value: If two shared_ptr are constructed (or made) from the same (non-shared_ptr) pointer, they will both be owning the pointer without sharing it, causing potential access problems when one of them releases it (deleting its managed object) and leaving the ...

Is shared_ptr a smart pointer?

The shared_ptr type is a smart pointer in the C++ standard library that is designed for scenarios in which more than one owner might have to manage the lifetime of the object in memory.

What does shared pointer 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.

Do we need to delete shared_ptr?

So no, you shouldn't. The purpose of shared_ptr is to manage an object that no one "person" has the right or responsibility to delete, because there could be others sharing ownership. So you shouldn't ever want to, either. Show activity on this post.


2 Answers

What is the difference between "owned pointer" and the "stored pointer" for std::shared_ptr?

Anytime you use the constructor template< class Y > shared_ptr::shared_ptr( const shared_ptr<Y>& r, element_type* ptr ) noexcept;, you have something that shares ownership with r, but dereferences to *ptr.

E.g. after

std::shared_ptr<std::pair<int, double>> pair = std::make_shared<std::pair<int,double>>(1, 2.);
std::shared_ptr<int> i(pair, &pair->first);
pair.reset();

the std::pair<int, double> is kept alive by i

like image 67
Caleth Avatar answered Sep 30 '22 16:09

Caleth


In order to support things like converting a shared_ptr<Derived> to shared_ptr<Base> even when no virtual destructor exists (which is allowed in that case even if it isn't a great idea in general for dynamically allocated classes), and for a few other features, shared_ptr needs to have one pointer to the object designated by each specific instance in that instance, and another one in the control block. The control block is used:

  • for counting "strong references" (owners of the dynamically allocated used ressource managed by the shared_ptr) and "weak references" (owners of the control block but not of the managed used resource);
  • to remember what to delete (pointer to the owned object) and how to delete it. The control block holds the exact pointer value that was passed to the original shared_ptr constructor.

Usually that value is used only for the purpose of deletion. Its value is examined (compared) only when you use owner_before. All other functions examine the pointer in each shared_ptr instance, not the pointer in the control block.

like image 42
curiousguy Avatar answered Sep 30 '22 16:09

curiousguy