【问题标题】:Why memleak with new operator in constructor's initialization list?为什么在构造函数的初始化列表中使用 new 运算符进行 memleak?
【发布时间】:2011-11-18 23:41:23
【问题描述】:

给定一个简单的 C++ 类,其中包含一个私有成员变量 name 和一个基本构造函数:

#include <QString>

class Testclass
{
  private:
    QString *name;

  public:
    Testclass(): name(new QString()) {}
};

为什么valgrind的memcheck报错1块8字节,用这个构造器肯定丢了?

【问题讨论】:

  • 动态分配name有什么意义?
  • 是在您创建对象时泄漏,还是稍后在您重新分配指针时(可能没有delete-ing 第一个指针)?
  • 您应该将您的任何new 视为一个大而闪烁的警告标志,并将其视为错误,直到您证明它实际上是正确的。

标签: c++ memory-leaks constructor new-operator valgrind


【解决方案1】:
~Testclass(){delete name;}

将堵塞您的泄漏。 C++ 不会(也不应该)为您这样做。

ETA:ildjarn 正确指出您还应该有一个复制构造函数和赋值运算符。

TestClass(const TestClass &cp): name(new QString(*(cp.name)) ) {}
const TestClass& operator=(const Testclass&rhs)
{
  (*name)=(*hrs.name);
  return *this;
}

否则,默认的复制构造函数或赋值运算符会导致同一块内存被删除两次。大多数需要析构函数的类应该替换或禁用默认的复制构造函数和赋值运算符。这就是所谓的“三法则”。

您可能想考虑简单地按值保存 QString,因为它本身很可能是一个轻量级容器类,如 std::string 或 std::vector。但如果你是 C++ 初学者,这样做一次是很有价值的一课。

【讨论】:

  • 当然,除了析构函数,他还需要一个拷贝构造函数和拷贝赋值运算符。 Rule of three
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多