-1

I known how weak_ptr is used, I read the following post:

About “circular reference”, I used weak_ptr but memory leak still happened

But there is a concept I can't understand yet.

I will demonstrate shared_ptr's created and released as I understand it:


1. shared_ptr pa created

reference_count of pa should be 0. Because no shared_ptr points to pa .

{/*scope 1*/

  shared_ptr<int> pa;
  // reference_count_pa = 0
}

2. I assign new shared_ptr<int> pb to pa in another scope

{/*scope 1*/

  shared_ptr<int> pa;

  {/*scope 2*/

    shared_ptr<int> pb = pa;
    // reference_count_pa = 1
    // reference_count_pb = 0
  }
}

reference_count of pa should be 1 because shared_ptr pb points to pa .

reference_count of pb should be 0 because no shared_ptr points to pb .

3. Now, a simple Circular Reference:

as is demonstrated in About “circular reference”, I used weak_ptr but memory leak still happened:

{/*scope 1*/

  shared_ptr<int> pa;

  {/*scope 2*/

    shared_ptr<int> pb = pa;
    pa = pb; //circular reference
    // reference_count_pa = 1
    // reference_count_pb = 1
  }
}

reference_count of pa should be 1 because shared_ptr pb points to pa

reference_count of pb should be 1 because shared_ptr pa points to pb

4. In the end of scope 2

pb is deleted because program walks out of scope 2 .

reference_count of pa is 0 now, because no shared_ptr points to pa .

reference_count of pb is still 1.

5. In the end of scope 1

reference_count of pb is 0 now because no shared_ptr points to pb .


The above steps are the reference_count as I understand it.

pa and pb are being deleted normally.

I'm confused.

Can anyone correct my error in the above steps?

Thanks!

anastaciu
  • 23,467
  • 7
  • 28
  • 53
curlywei
  • 682
  • 10
  • 18
  • 7
    There is no circular reference there. Also, you're not actually allocating memory anywhere so the reference count is zero everywhere. – Indiana Kernick Jan 16 '20 at 09:27
  • 2
    The reference count tells you how many `shared_ptr`s are sharing an object. `shared_ptr pb = pa;` does not mean that `pb` points to `pa`, but that both `pb` and `pa` share the same `int`, making the reference count 2. – molbdnilo Jan 16 '20 at 09:27
  • 1
    You can check `pa.use_count()` and `pb.use_count()` to see the reference count yourself – Indiana Kernick Jan 16 '20 at 09:28
  • There are many "should be" assumptions here that you could take a few minutes to verify. – molbdnilo Jan 16 '20 at 09:29
  • Hi Kerndog73: I forget to use `std::make_shared` – curlywei Jan 16 '20 at 09:38
  • About reference counting: imagine that all shared pointers just point to a proxy object that holdes the shared pointer and a reference counter. Creating a new shared pointer with a raw pointer would create a new proxy object, reference count 1, creating a new shared pointer from another would just increment the reference count. Destruction is simple: if reference count is 1, destroy proxy and shared object, otherwise just decrement reference count. Assignment gets a bit more complicated, combines both destruction and construction, but basic idea remains... – Aconcagua Jan 16 '20 at 10:18

2 Answers2

2

Does anyone correct my error in above step ?

Firstly, that isn't a circular reference. Secondly there isn't any reference counting in your code, because you have no int to count references to.

A circular reference is of the form

struct Node {
    std::shared_ptr<Node> next;
};

int main() {
    std::shared_ptr<Node> a = std::make_shared<Node>();
    std::shared_ptr<Node> b = std::make_shared<Node>();

    a->next = b;
    b->next = a;
}
Caleth
  • 52,200
  • 2
  • 44
  • 75
0

Did you mean use_count when you write reference_count? The latter cant be found in cpp-reference.

The answer is a shared_ptr counts the number of all (this one and other) managed pointers, that points to the same object (pointee). Hence, all managed pointers pointing to the same object will return the same use_count. (This adresses your conclusion of 2.).

Your "circular" reference" in 3 isn't a circular reference, but two shared pointers pointing to nothing. I recomend std::make_shared> to create an (managed)Object that is managed be a shared pointer. BTW, a week pointer is pointing to a managed Object that is aware of the existence of this Object.

Just read the manual, https://en.cppreference.com/w/cpp/memory/shared_ptr. Here you find the description of use_count:

long use_count() const noexcept;

Returns the number of different shared_ptr instances (this included) managing the current object. If there is no managed object, ​0​ is returned.

Xantopp
  • 64
  • 7