What is a safe way to accessing member variables through a shared object in C++?
In the code below, I make a shared variable and then a pointer to a member variable of it. However, the use_count remains unchanged and when I reset the shared variable the original variable is reset but not the pointer to member.
In other words, I could introduce some bugs by using b. The object it is pointing to shouldn't exist anymore.
#include <iostream>
#include <memory>
using namespace std;
struct A
{
int y;
A(int x)
{
y = x;
}
};
int main()
{
auto a = make_shared<A>(1);
cout << "a count: " << a.use_count() << endl; //prints a count: 1
auto b = a->y;
cout << "a count: " << a.use_count() << endl; //still prints a count: 1
a.reset();
cout << "a value: " << a << endl; //prints a value: 0
cout << "b value: " << b << endl; //prints b value: 1
return 0;
}
What is a safe way to accessing member variables through a shared object in C++?
You are already doing it. The code you showed is safe.
In the code below, I make a shared variable and then a pointer to a member variable of it.
No, you don't. A::y
is an int
. In the auto b = a->y;
statement, auto
deduces to int
, not to int&
or int*
. So, you are creating a new int
whose value is a copy of y
. There is no pointer to y
.
If you wanted something like that, you would have needed to use one of these instead:
auto &b = a->y;
...
cout << "b value: " << b << endl;
auto *b = &(a->y); // or just: auto b = ...
...
cout << "b value: " << *b << endl;
However, the use_count remains unchanged
Correct, because you are not assigning a
to another instance of shared_ptr<A>
. That is what use_count
represents - the number of shared_ptr
objects that are sharing the same object in memory.
when I reset the shared variable the original variable is reset but not the pointer to member.
Of course, because b
is independent of a
and is not a pointer to anything related to a
.
In other words, I could introduce some bugs by using b.
No, because b
is not linked to a
, so resetting a
has no effect on b
.
Now, if you did manage to accomplish what you are asking for (making b
be a pointer to y
), it is your responsibility to make sure the A
object that y
was accessed from remains valid in memory until you are done using b
, otherwise dereferencing b
will be undefined behavior. The STL won't save you from doing something stupid behind its back, like accessing an A
object's member via a raw pointer after the object has been destroyed.