Reputation: 23802
Consider the following function:
void example(void **ptr){
std::cout << *ptr << "\n"; // pointer value
std::cout << ptr << "\n"; // pointer address
std::cout << **reinterpret_cast<int**>(ptr); // value
}
The function signature cannot be changed.
Is the following code valid, or should I use raw pointers?
int main()
{
std::unique_ptr<int> x = std::make_unique<int>(20);
std::cout << x.get() << "\n"; // pointer value
std::cout << &x << "\n"; // pointer address
example(reinterpret_cast<void**>(&x));
}
Upvotes: 3
Views: 344
Reputation: 66431
It is not valid and has undefined behaviour.
(If it appears to work, it's because your particular implementation happens to store the unique_ptr
's underlying pointer as its first member in this particular situation. It is still 100% pure crystal-clear undefined behaviour, though.)
If you can't change the function, you need to pass it something that actually is an int**
- &x
is a std::unique_ptr<int>*
, and no amount of casting can make a valid int**
from it.
(I have found that it's often a mistake to think of the smart "pointers" as pointers.)
The way to get a pointer to the underlying object in a smart "pointer" is through get()
:
int* p = x.get();
and then you can pass a pointer to p
(you still need to cast it, though):
example(reinterpret_cast<void**>(&p));
Upvotes: 3
Reputation: 118352
Generally only void *
have special rights and privileges when it comes to playing funny games with casting. However, given the situation that you have to work with:
example(reinterpret_cast<void**>(&x));
Note that you're passing &x
and laundering it with reinterpret_cast
. In example()
you should do exactly the opposite:
void example(void **ptr)
{
auto x_ptr = reinterpret_cast<std::unique_ptr<int> *>(ptr);
Now you have a std::unique_ptr<int> *
to work with. You can proceed according to your original plans. If you wish, your next step can be:
auto &x=*xptr;
And this x
is the same x
as in your main
, for all practical purposes (and it is).
Upvotes: 1