Reputation: 195
I am struggling to understand the difference in behaviour of a raw pointer and a unique_ptr. I have class A
with a variable x
and class B
with a pointer to an instance of A
:
class A
{
public:
int x;
};
A::A(int y) : x(y)
{
}
class B
{
public:
B(A &);
A *p;
};
B::B(A &a)
{
p = &a;
}
This behaves as I would expect:
int main()
{
A a(2);
B b(a);
cout << a.x << " " << b.p->x << endl;
a.x = 4;
cout << a.x << " " << b.p->x << endl;
}
gives
2 2
4 4
Changing the raw pointer to a std::unique_ptr gives a different result:
class A
{
public:
int x;
};
A::A(int y) : x(y)
{
}
class B
{
public:
B(A &);
std::unique_ptr<A> p;
};
B::B(A &a)
{
p = std::make_unique<A>(a);
}
gives
2 2
4 2
Have I fundamentally misunderstood something about unique_ptrs?
Upvotes: 0
Views: 757
Reputation: 16841
Try reading the following expression from the smart pointer version:
std::make_unique<A>(a);
"make a unique A
from a
" (no mention of pointers!)
The result is a unique_ptr
, but when reading the expression, read it as making (an object whose type is) the template parameter. The function parameters are parameters to the constructor. In this case, you are making an A
object from an A
object, which pulls in the copy constructor.
Once you understand that the smart pointer version is making a new A
object (and your raw pointer version does not), your results should make sense.
The "unique" in "unique A
" might be tricky to understand. Think of it as an object that no one else can lay claim to. It might be a copy of another object, but, taking the role of the unique_ptr
, it is your copy, your responsibility to clean up after, and no one else's. Your preciousss, which you will not share (c.f. std::make_shared
).
Note that a local variable (like the a
in the main
function) is the responsibility of the compiler, so it is ineligible to be the object to which a unique_ptr
points (or any smart pointer, for that matter).
Upvotes: 0
Reputation: 56
make_unique
creates a fresh object, one that that unique_pt
has exclusive access to. So in the second example you have two objects, not one and when you set change the value of a.x
in the first object it doesn't effect the other object held by the unique_ptr
.
Upvotes: 2
Reputation: 98425
A unique pointer needs to own whatever it points to. Your code can be made to work - just substituting unique_ptr type and leaving everything else unchanged (no make_unique). But it will have undefined behavior, since you’ll create a unique pointer to an object that is owned elsewhere.
To compare apples to apples, the raw pointer code should read p=new A(a);
. That’s what make_unique
does.
Upvotes: 1