Search code examples
c++c++17c++14shared-ptr

Shared_ptr instance is not set for an object as expected


I have a struct A which has a member another struct C. So A with c1Ptr_ as member. I use 2 structs S and N. N has as member A, a_ and S has as member C, c_. After I instantiated A and create for S a c object using the created A object and I pass the created A object to N I would expect to have the A->c1Ptr_ in N as well.
Thank you.

 #include <iostream>
    #include <memory>
    using namespace std;
    
    
    
    struct C1 
    {
        C1(int x):x_(x)
        {
            std::cout<<"-C1: x_: " << x_ << std::endl;
        }
        int x_;
        ~C1()
        {
            std::cout<<"-DC1: x_: " << x_ << std::endl;
        }
    };
    
    using C1ptr = std::shared_ptr<C1>;
    
    
    
    struct A
    {
       C1ptr c1Ptr;
    };
    
    
    struct S
    {
       S(C1ptr& c1Ptr):c1Ptr_(c1Ptr)
       {
           
       }
       
       C1ptr c1Ptr_;
    };
    
    struct N
    { 
        N(std::shared_ptr<A> a):a_(a)
        {
            
        }
        std::shared_ptr<A> a_;
    };
    
    
    
    int main()
    {
       std::shared_ptr<A> a = std::make_shared<A>();
       S s(a->c1Ptr);
       N n(a);
       
       s.c1Ptr_ = std::make_shared<C1>(12);
       
       if (n.a_->c1Ptr)
       {
           std::cout<<"c1Ptr is set for N\n";
       }
       else
       {
           std::cout<<"c1Ptr is NOT set for N\n"; // why c1Ptr is not set for n.a_ ? 
       }
    
        return 0;
    }

Solution

  • You can try to work this out on your own by drawing the objects a, s, and n and their contents, and what their contents point to:

    auto a = std::make_shared<A>();  // a(c1Ptr_ = null)
    S s(a->c1Ptr_);                  // a(c1Ptr_ = null), s(c1Ptr_ = null)
    N n(a);                          // a(c1Ptr_ = null), s(c1Ptr_ = null), n(a_ = a)
                                     // [n.a_ points to a]
    

    After this initial block of instructions:

    • a and s have their shared pointer members c1Ptr_ with a value of nullptr.
    • n has its shared pointer member a_ pointing to the object a.
    s.c1Ptr_ = std::make_shared<C1>(12);  // (1) a(c1Ptr_ = null), s(c1Ptr_->x_ = 12 ), n(a_ = a) 
                                          //     [and you modify s]
    if (n.a_->c1Ptr_) {
        std::cout << "c1Ptr is set for N\n\n";
    }
    else {
        std::cout << "c1Ptr is NOT set for N\n\n";  // (1)
    }
    

    Here:

    • you just modify s.c1Ptr_, but that doesn't affect a, and ultimately, n.
    • s.c1Ptr_ was originally set to point to the same C1 object as a.c1Ptr_ (actually, nullptr); now you're just making it point to something else.
    a->c1Ptr_ = std::make_shared<C1>(15);  // (2) a(c1Ptr_->x_ = 15 ), s(c1Ptr_->x_ = 12 ), n(a_ = a)
                                           //     [and you modify a]
    if (n.a_->c1Ptr_) {
        std::cout << "c1Ptr is set for N\n\n";  // (2)
    }
    else {
        std::cout << "c1Ptr is NOT set for N\n\n";
    }
    

    What would have happened if you had changed a->c1Ptr_ instead? Since n->a_ points to a and we are modifying a, n->a_->c1Ptr_ is also set.

    [Demo]