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));
}
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));