在返回新实例时,在运算符中创建临时堆变量是否会导致内存泄漏

Does creating temp heap variables in an operator overloads when returning a new instance cause a memory leak?

本文关键字:变量 是否 泄漏 内存 新实例 返回 实例 运算符 创建      更新时间:2023-10-16

例如,想象一个+运算符重载来连接两个字符串;在本例中,两种奶酪的名称。在这里,我使用了在堆上创建的tmp变量。当方法退出时,这是否会导致内存泄漏?

Class Cheese {
private:
    int nameLen; // Length of name
    char * name; // C string
public:
    Cheese(char * str); // Constructor
    int getNameLen(); // Returns length of name
    char * getName(); // Returns name
}

}

Cheese Cheese::operator + (const Cheese & rhs) {
    char * tmp = new char[nameLen + rhs.getNameLen()];
    strcpy(tmp, name); 
    strcat(tmp, rhs.getName());
    return Cheese(tmp); // Is this a problem? Where does tmp get deleted?
}

用法:

Cheese c1("mozzarella");
Cheese c2("provolone");
printf("Cheese Blend: %s", (c1 + c2).getName());

因此,返回值将创建Cheese的另一个实例。我关心的是在堆上创建的tmp是否会造成内存泄漏。它从未被删除,由于我将它作为return语句的一部分,我不知道应该在哪里删除它。

这是合理的担忧吗?我需要这个tmp变量吗?还是我可以聪明一点,根本不使用它?最好的做法是把它放在堆栈上,如下所示吗?最佳做法是什么?

char * tmp[len + rhs.getLen()];

Thx!

return Cheese(tmp); // Is this a problem? Where does tmp get deleted?

如果Cheese的构造函数复制输入参数,则会出现问题。

当函数返回时,可以使用智能指针删除tmp使用的内存。

int len = nameLen + rhs.getNameLen() + 1; // Need the +1 for the null terminator
std::unique_ptr<char, std::default_delete<char[]>> tmp(new char[len]);
strcpy(tmp.get(), name); 
strcat(tmp.get(), rhs.getName());
return Cheese(tmp.get());

若使用std::string作为成员变量name的类型,而不是char*,就可以消除代码中这些不必要的复杂性。如果这样做,就可以去掉nameLen成员变量。然后,上述函数可以简化为:

Cheese Cheese::operator + (const Cheese & rhs) {
    return Cheese(this->name + rhs.name);
}