Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the std::unique_ptr constructor accept an external pointer?

Tags:

c++

I'm relatively new to cpp, and am learning about smart points. I'm wondering the following:

Why is constructing an std::unique_ptr with an lvalue allowed?

Wouldn't it be safer to only allow the construction of an std::unique_ptr with rvalues to avoid evil things?

std::unique_ptr<int> createInt() {
    int* a = new int(99);
    std::unique_ptr<int> foo(a);
    delete a;
    return foo;
}

I realize you'd have to be crazy to write something like that but I'd be nice to have the compiler yell at you for it. So I'm left wondering, why is lvalue initialization of unique_ptr a thing?

EDIT: User @aler egal put my thoughts more elagantly:

"In principle, you could have a constructor unique_ptr<int>(int*&& ptr) which assumes ownership of ptr and then sets it to null. That would prevent a use-after-free in this specific example (because you'd be forced to std::move(a) and because calling delete on a null pointer has no effect) but it would be a very strange anti-pattern."

like image 992
frankelot Avatar asked Jan 25 '23 18:01

frankelot


1 Answers

This is a classic example of what a dangling pointer is! In contrast to what smart pointers may seem, they are simply wrappers over normal (raw) pointers, which can manage memory on their own and give you some added functionalities.

Consider the following example:

int* someFunc() {
    int* ptr;
    int* ptr2 = ptr;
    delete ptr;
    return ptr2;
}

This is what you are essentially doing.
They have been made such that they can be used instead of raw owning pointers at all times; meaning, they can be dangled too! So, if they are not allowed lvalue initialisation, that's one use case where you can't use a smart pointer, although I agree, this is one case where you are not to use either!

The above code with smart pointers will be exactly what you tried.

Now, C++ leaves logic to you... entirely. If you want to shoot yourself in the foot, go ahead, C++ won't bark. C++ does not check for memory usage and buffer overflows and access of deleted memory. Simply speaking, it's the job of a C++ programmer and if he/she wants to shoot himself/herself in the foot, he/she's free to do so!


Also, it is usually recommended to use std::make_ptr() over the ctor, as the former is exceptions enabled

like image 150
kesarling He-Him Avatar answered Apr 27 '23 01:04

kesarling He-Him