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;
}
CodePudding user response:
shared_ptr doesn't share a pointer, it shares ownership of a pointer.
This means that you can change individual shared_ptr to point to other things, indepnendent of other shared_ptr's, but as soon as there's no shared_ptr pointing at something, that something get's deleted. Think of it as adding a counter to the pointer. When you create, delete or reassign a shared_ptr to something other than nullptr, you will increment or decrement the counter. If the counter reaches 0 (usually on a delete) then it also deletes the pointer.
In your case you are copying a nullptr from a. So you have two shared_ptr both storing nullptr. Then you change one of them to point to a new thing (12). This won't change anything else in memory, or specifically the value of other shared_ptrs.
CodePudding user response:
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:
aandshave their shared pointer membersc1Ptr_with a value of nullptr.nhas its shared pointer membera_pointing to the objecta.
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 affecta, and ultimately,n. s.c1Ptr_was originally set to point to the sameC1object asa.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.
