在这种情况下,我应该删除指针吗?

Should I delete the pointer in this case?

本文关键字:指针 删除 我应该 这种情况下      更新时间:2023-10-16

在我自己的字符串类中(只是为了学习),我重载了操作符+是否需要清理tmpPtr所指向的内存?

String String::operator+(const String& rv) const
{
    size_t newLength = length + rv.length;
    char* tmpPtr = new char[newLength + 1];
    strcpy(tmpPtr, ptr);
    strcpy(tmpPtr + length, rv.ptr);
    String S(tmpPtr);
    delete[] tmpPtr;
    return S;
}

我可以这样改变这个方法吗?

String String::operator+(const String& rv) const
{
    size_t newLength = length + rv.length;
    char* tmpPtr = new char[newLength + 1];
    strcpy(tmpPtr, ptr);
    strcpy(tmpPtr + length, rv.ptr);
    return S(tmpPtr);
}

如果需要构造函数和析构函数:

String::String(const char* str)
{
    setString(str, strlen(str));
}
String::String(const String& str)
{
    setString(str.ptr, str.length);
}
void String::setString(const char* str, size_t size)
{
    ptr = new char[size + 1];
    strcpy(ptr, str);
    length = size;
}
String::~String()
{
    delete[] ptr;
}

正如Vlad所说,这取决于您如何实现构造函数。

如果构造函数只是获取指针的所有权,然后在析构函数中删除它,那么这里不需要delete[]。然而,这是有问题的,因为这意味着你不能安全地从字符串字面量直接构造一个String实例。

通常,编写构造函数的更好方法是将传入的指针的内容复制到一个新的内存块中,然后存储指向该内存块的指针。这意味着String的内存使用是对称的:它释放它分配的所有内存,而不释放其他内存。这意味着,如果你new[]某样东西,然后将该指针传递给String的构造函数,你仍然需要delete[]它。

然而,无论哪种方式,这两种选择都不是特别适合这里。相反,您应该这样做:

String String::operator+(const String& rv) const
{
    size_t newLength = length + rv.length;
    // Create a string with enough backing storage
    String S(newLength + 1);
    strcpy(S.ptr, ptr);
    strcpy(S.Ptr + length, rv.ptr);
    return S;
}

这确保是String实例管理所涉及的内存,因此您可以获得通常从构造函数/析构函数对获得的所有清理保证。

Edit:有了构造函数体,我们可以得出结论,您采用了第二种方法。因此,如果您继续使用这种方法,则需要对内存进行delete[]

由于构造函数String::String调用的String::setString成员函数在动态内存中创建了自己的char数组,并复制了传入字符串的内容:

void String::setString(const char* str, size_t size)
{
    ptr = new char[size + 1];
    strcpy(ptr, str);
    length = size;
}

原来在String::operator+中创建的内存不再需要,它被存储在任何地方,因此如果不删除就会泄漏。所以,是的,你需要delete[]

是。一般来说,您需要删除由new分配的内存。

维基说:

在c++编程语言中,delete操作符调用给定实参的析构函数,并将new分配的内存返回给堆。[1]每次调用new都必须调用delete,以避免内存泄漏。

c++ 11.3.8对象生存期(p4):

…如果没有显式调用析构函数,或者没有使用delete表达式(5.3.5)来释放存储,则不应隐式调用析构函数,并且任何依赖析构函数产生的副作用的程序都具有未定义的行为。


EDIT:根据OP的编辑,由于析构函数正在释放内存,在这种情况下不需要显式地删除ptr 。但仍然需要使用delete[]运算符删除tmpPtr