当 class 包装了一个 STL 容器和一个指针时,我是否应该在我的 class 的析构函数中销毁 STL 容器?

Should I destroy STL containers in my class's destructor, when the class wraps both a STL container and a pointer?

我有点理解这样一个事实,即 class 的包装 STL 容器将在 class 的实例超出范围时自动销毁。因此,当 class 仅包装 STL 容器时,我不必编写析构函数。但是,如果 class 还必须管理一些指针怎么办?

说在某些 CUDA 开发中,我想要一个 class 来处理设备指针和 STL 容器。

class Image{
    private:
        float *data_device;
        std::array<int, 2> shape;
    public:
        // some constructors and methods
        ~Image(){
            cudaFree(data_device);
            // what to do with the STL array?
        }
};

在上面的例子中,我需要析构函数来释放 data_device 的内存。但是我应该处理 STL 数组吗?如果是这样,我怎样才能正确销毁 shape

But should I deal with the STL array?

不,你不应该。

std::array 析构函数自动销毁数组的每个元素。

你创建一个析构函数来手动拆除你 class 管理的任何东西是正确的。

但是,这样做并不能阻止其他一切被破坏。在 析构函数运行后,您的成员仍将被自动析构;你的析构函数是另外

所以你做对了。

您可以想象,析构函数的右大括号还调用了每个成员(和基类)的析构函数,调用顺序与构造函数相反。

因此,您无需对设计合理的成员执行任何额外操作,所有 std 容器都是如此。但是让我们后退一点。

But what if the class also have to manage some pointer(s)?

你不应该写这样的class。相反,您使用 class 的 唯一 工作是管理 恰好一个 指针作为 "some pointer" 的替代方法。作为奖励,您现在不必担心 double-free,因为 Image 没有默认的复制构造函数

// cuda Deleter for std::unique_ptr
struct CudaFree
{
    void operator()(float * ptr) { cudaFree(ptr); }
}

class Image{
    private:
        std::unique_ptr<float, CudaFree> data_device;
        std::array<int, 2> shape;
    public:
        Image(/* ? */)
          : data_device(cudaAlloc()/* ? */), 
            shape(/* ? */) 
        {/* ? */}
        // similarly other constructors
        // other members
        // implicit destructor does the right thing
};