为什么 std::unique_ptr 的 get() 获取的原始指针无法删除对象以及它是如何实现的

amo*_*ont 1 c++ smart-pointers unique-ptr

正如下面的代码所示,我尝试通过从 unique_ptr 获取的原始指针来删除该对象。但是,正如输出所示,编译器报告了错误。然而,对于原始指针,我们可以这样做int *p1 = new int{100}; int* p2 = p1; delete p2;

此外,我认为 unique_ptr 通过移动语义来维持其所有权。由于unique_ptr的get()函数返回的是原始指针,那么unique_ptr如何仍然拥有该对象的所有权呢?同时,为什么原始指针没有获得所有权。同时,我很困惑这是如何实现的。谢谢。

#include <iostream>
#include <memory>

int main(int argc, char const *argv[])
{
    std::unique_ptr<int> newPtr = std::make_unique<int>(1234);
    std::cout << *newPtr << std::endl;
    int* rawInt = newPtr.get();
    *rawInt = 200;
    delete rawInt;
    rawInt = nullptr;
    std::cout << *newPtr << std::endl; 
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

该代码在 MacO 上执行,输出为:

输出

Mil*_*nek 5

std::unique_ptr是一个非常简单的类。从概念上讲,它基本上就是这样:

template <typename T>
class unique_ptr
{
private:
    T* ptr;

public:
    unique_ptr(T* p) ptr{p} {}
    ~unique_ptr() { delete ptr; }

    T* get() { return ptr; }
    T* release() {
        T* p = ptr;
        ptr = nullptr;
        return p;
    }

    // other stuff
};
Run Code Online (Sandbox Code Playgroud)

它只有一个指针成员,并delete在其析构函数中保存指向的对象。事实上,还有更多内容,但本质上就是这样。

该成员仅返回 的托管指针get的副本。unique_ptr就是这样。由于unique_ptr的指针成员仍然指向该对象,因此它的析构函数仍将指向delete该对象。如果您还delete通过另一个指向该对象的指针,那么它将获得deleted 两次,这会导致未定义的行为。

release另一方面,成员函数在返回其原始值的副本之前将unique_ptr的指针成员设置为。nullptr由于其成员指针为空,因此其析构函数不会删除任何内容。