我是不是应该检查并释放 VLA 类的分配运算符 (operator=) 中的指针

Posted

技术标签:

【中文标题】我是不是应该检查并释放 VLA 类的分配运算符 (operator=) 中的指针【英文标题】:Should I check and free pointer in VLA class' assign operator (operator=)我是否应该检查并释放 VLA 类的分配运算符 (operator=) 中的指针 【发布时间】:2021-09-29 21:31:26 【问题描述】:

假设我们有一个简单的变长数组类,如下所示:

struct VLA 
    double* d=nullptr;
    int dim;

让我想知道的是,在 operator= 中,我应该在 malloc/new 一个新数组之前检查(如果不是 nullptr,则可能是免费/删除)d?由于赋值不同于复制构造函数,它最初也可能携带一个数组。


如下例:

operator=(VLA &other) 
    double *tmp=new double[dim];
    memcpy(tmp, other.d, sizeof(double)*other.dim);
    delete[]d;
    d=tmp;
    dim=other.dim;

delete[]d 是必需的吗?

【问题讨论】:

VLA 指的是 C 中可用的一些特定结构。free 和 malloc 标记在这里也没有那么相关 这能回答你的问题吗? ***.com/questions/4172722/what-is-the-rule-of-three。好吧,我想不是直接的,但你需要更多 delete 才能拥有一个不会被严重破坏的课程 也许你已经拥有了更多的特殊成员函数。您应该将它们包括在问题中,因为它们密切相关。 在重新分配对象时,您有责任释放旧内存以防止泄漏。 delete 将安全地处理空指针。不需要断言new 不为空,如果不能分配就会抛出异常。如果您希望 new 在分配失败时返回 null,请使用 new(::std::nothrow) double[] 例如,如果没有适当的构造函数,delete 可能会在 d 未初始化的情况下调用。 【参考方案1】:

operator= 内,我应该检查(如果不是nullptr,则可能是免费/删除)d 在 malloc/new 一个新数组之前?

delete[]d 是必需的吗?

如果你打算用new[]分配一个新数组,那么是的,你需要用delete[]释放旧数组,否则会泄露。是否在分配新数组之前或之后执行此操作取决于您,但我会在之后执行,以防分配新数组失败。

请注意,如果新的dim 与旧的dim 的值相同,则可以跳过new[]/delete[],并使用copy-swap idiom当你分配一个新数组时:

VLA(const VLA &other) 
    d = new double[other.dim];
    memcpy(d, other.d, sizeof(double) * other.dim);
    dim = other.dim;


VLA& operator=(const VLA &other) 
    if (this != &other) 
        if (dim == other.dim) 
            memcpy(d, other.d, sizeof(double) * other.dim);
        else 
            VLA temp(other);
            std::swap(d, temp.d);
            std::swap(dim, temp.dim);
        
    
    return *this;

不过,您确实应该完全手动使用std::vector 而不是new[]/delete[]。让std::vector为你处理数组:

#include <vector>

struct VLA 
    std::vector<double> d;
    int dim() const  return d.size(); 

    // compiler-generated copy constructor will "do the right thing"...
    // compiler-generated operator=() will "do the right thing"...
;

【讨论】:

以上是关于我是不是应该检查并释放 VLA 类的分配运算符 (operator=) 中的指针的主要内容,如果未能解决你的问题,请参考以下文章

如果分配该数组引发异常,你应该释放一个数组吗?

在 C++ 中删除其类的实例后,分配给 cpp 中定义的全局静态变量的内存是不是被释放?

如何验证两个检查点之间是否已释放所有内存分配?

重载类的new和delete运算符成员函数

不检查复制赋值运算符是不是将对象分配给自身真的安全吗?

在C中释放动态分配的内存