How to assign the address of an existing object to a smart pointer?
Allow me to disappoint you, but you don't. You have there a reference, which can point to either a dynamically allocated object or a stack allocated object, or, maybe, an object in a dynamically allocated array, which was not individually allocated.
You want to place its address in a class that will automatically call delete on that address. Which is invalid for most situations presented above. That is wrong. So passing a reference and putting the address of the reference in a smart pointer should never be done, ever. Especially not with reset().
At most, what you may want to do is initialize the smart pointer with the newly allocated object, for example:
auto ptr = std::unique_ptr<X>(new X(p1, p2));
Do not ever take the address of a reference. Ever. For no reason. It's morally wrong. It's not because the use of reference addresses is invalid, because it can be valid use; it's because two months later the new colleague will want to use that address with a smart pointer because that's how (s)he heard it's done nowadays, and then come to Stack Overflow and read that they should use „reset” for that pointer. Which is wrong, painfully wrong.
Try std::unique_ptr::reset
void foo(bar &object){
std::unique_ptr<bar> pointer;
pointer.reset(&object);
}
But be aware this is not recommended, you should not create a unique_ptr
to a reference that is being passed to a function. At the end of the function, when pointer
is being destroyed it will try to destroy object
as well, and it won't be available outside the function call, resulting in an access memory error.
Example: This will compile, but give a runtime error.
struct bar{ int num;};
void foo(bar &object){
std::unique_ptr<bar> pointer;
pointer.reset(&object);
}
int main()
{
bar obj;
foo(obj);
obj.num; // obj is not a valid reference any more.
return 0;
}
On the other hand you might want to consider using shared_ptr this can help you to decide: unique_ptr or shared_ptr?.
You can only assign another unique_ptr
or the nullptr
. If you think about it, this makes sense, too (though reset
will let you do what you want, but I think this is actually a bug or deficiency in unique_ptr
).
A unique_ptr
is the exclusive owner of the pointed-to object. When it goes out of scope, it will delete the object.
This means that your function has sink semantics. The pointer you pass in (or rather the pointed-to object") is consumed, that is, it "disappears" (sinks) inside the function. You pass in an object by reference (an object which is not even necessarily heap-allocated, prepare for a surprise if you pass in an object with automatic storage!) and suddenly it's gone. Bang.
Sink semantics should be communicated properly. You should pass a unique_ptr
as function parameter. Unique pointers cannot be copied, so this will force the user of that function to use std::move
, creating awareness of what is acutally happening.
Having an object "disappear" is a nasty surprise, this shouldn't just happen unintentionally.