【问题标题】:Is it true that unique_ptr which points to an array will automatically free dynamic memory after calling release()?指向数组的unique_ptr是否会在调用release()后自动释放动态内存?
【发布时间】:2019-12-11 05:57:33
【问题描述】:

据我所知,调用std::unique_ptr<T,Deleter>::release 只会转移所有权,不会释放动态内存。

来自C++ Primer 5th:

p2.release(); // WRONG: p2 won't free the memory and we've lost the pointer
auto p = p2.release(); // ok, but we must remember to delete(p)

但几页后它写道:

该库提供了unique_ptr 的一个版本,可以管理由 新的。要使用unique_ptr 管理动态数组,我们必须包含一对 对象类型后的空括号:

// up points to an array of ten uninitialized ints
unique_ptr<int[]> up(new int[10]);
up.release();   // automatically uses delete[] to destroy its pointer

类型说明符 (&lt;int[]&gt;) 中的括号表示 up 指向不 一个 int 但到一个 int 数组。因为 up 指向一个数组,所以当 up 销毁它管理的指针,它会自动使用delete[]。


那么std::unique_ptr&lt;T,Deleter&gt;::releas 对动态分配的数组的处理方式是否不同,即调用release() 后会自动释放分配的内存?如果它是真的,那么它也表明不能转移动态数组的所有权。到目前为止,我在网上找不到任何权威的参考资料。

【问题讨论】:

  • 我认为这不是真的。我在 cppreference 上找不到它,也无法重现:wandbox。不调用析构函数。内存泄露。
  • 发布 -> 重置错字

标签: c++ unique-ptr


【解决方案1】:

我看了一点,我猜这只是作者的一个错误。 cppreference.com makes no reference to any array specialization for release。为了确定,我继续检查了 libc++ 的源代码(LLVM 的标准库实现)。 This is the implementation for std::unique_ptr&lt;T[], Deleter&gt;::release。如您所见,它没有调用delete[]。我的猜测是作者打算将up.reset(); 写成this does free the memory。

【讨论】:

    【解决方案2】:
    // up points to an array of ten uninitialized ints
    unique_ptr<int[]> up(new int[10]);
    up.release();   // automatically uses delete[] to destroy its pointer
    

    这是不正确的。 up.release() 没有为它管理的数组调用 delete[]。它只是释放数组的所有权并返回指向它的指针。因此,编码员有责任致电delete[]。

    我认为您与std::unique_ptr&lt;T, Deleter&gt;::reset() 混淆了,它确实释放了分配的内存。

    演示:

    #include <iostream>
    #include <memory>
    
    class Test
    {
    public:
        Test() { std::cout << "Test()" << std::endl; }
        ~Test() { std::cout << "~Test()" << std::endl; }
    };
    
    int main()
    {
        std::unique_ptr<Test[]> up(new Test[3]);
        auto ptr = up.release();
    
        return 0;
    }
    

    输出:

    Test()
    Test()
    Test()
    

    没有调用析构函数。所以我们有内存泄漏!避免这种情况的唯一方法是在auto ptr = up.release(); 之后调用delete[] ptr;

    注意:从 C++14 开始,您可以编写:

    std::unique_ptr<CTest[]> up = std::make_unique<CTest[]>(3);
    

    这是better,而不是显式new-ing,因为如果抛出异常,它不会泄漏。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-02
      • 1970-01-01
      • 1970-01-01
      • 2017-06-04
      • 2015-05-16
      • 1970-01-01
      相关资源
      最近更新 更多