I'm fairly new to smart pointers and I couldn't understand the result of the code I attached below. Basically the reference count and the raw pointer it self of a shared_ptr
object is changed after it is passed to another unique_ptr
object.
So the code goes like this.
typedef shared_ptr<int> sp;
class bar {
public:
const sp& x; // line 3: if change this line to "const sp x;" then it's fine
bar(const sp xx) : x(xx) {
cout << "bar: count=" << x.use_count() << "; addr=" << x.get() << endl;
}
void test() {
cout << "test: count=" << x.use_count() << "; addr=" << x.get() << endl;
}
};
int main() {
auto p = make_shared<int>(0);
auto b = make_unique<bar>(p);
b->test();
}
If I compile and run the code, it prints out:
bar: count=2; addr=0x557c8b02dec0
test: count=1224736736; addr=0x7ffdb5cbd5c0
So the ref count and pointer are both changed. And it looks like some uninitialized value.
But if I change line 3 to const sp x;
then both values look normal:
bar: count=3; addr=0x5590f026eec0
test: count=2; addr=0x5590f026eec0
Sorry about the bad namings since it's a quick minimum case I came up with to address my question. I feel it has something to do with how unique_ptr
works, but I'm not sure.
Can someone shed some light and help me understand why the code behaves like that?
Thanks
CodePudding user response:
Over here:
const sp& x;
bar(const sp xx) : x(xx)
You assign the shared pointer into a local variable, xx
, and then bind the const reference x
to that local variable. When the constructor concludes its run, that local variable goes out of scope, leaving you with a reference to Eldritch Horrors and undefined behavior.
To explain your observation regarding the removal of the &
:
Removing the &
prevents this because in that case you just assign the shared pointer straight into x
which henceforth is not dependent on the local variable xx
, and so is unaffected by its going out of scope.
To expand: another thing you could do instead, if what you wanted was to hold a reference, is to set xx
to be a reference itself (e.g. bar(const sp& xx) : x(xx)
); in this case you'd be binding x
to p
.