Search code examples
c++c++11smart-pointers

Passing smart pointer to function through non smart pointer argument


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

Live sample


Solution

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