我的C ++非常生疏,所以现在我开始将它用于业余爱好项目,我必须“升级” - 再次...
#include "stdafx.h"
#include "stdlib.h"
class a
{
public:
void call() { printf("CALL called\n"); }
};
class b
{
public:
b() { this->pointer = new a; }
void call() { this->pointer->call(); }
private:
a* pointer;
};
int _tmain(int argc, _TCHAR* argv[])
{
b t;
t.call();
system("PAUSE");
return 0;
}
这会导致内存泄漏吗?如果程序决定它不再需要它们,我怎么能删除指针呢?
“删除t”是否足够或者是否会产生内存泄漏?
答案 0 :(得分:6)
pointer
中的 b
已分配,但从未删除。您需要为b
定义一个删除a
的析构函数,否则每次a
消失时您都会泄漏pointer
指向的b
范围:
b::~b()
{
delete pointer;
}
答案 1 :(得分:2)
~b() { delete pointer; }
对于每个新内容,必须有匹配的删除。
答案 2 :(得分:2)
类b
包含您分配但从不自由的指针。是的,这将导致内存泄漏。
处理这个问题的老式方法是删除b
析构函数中的指针,因为你知道它永远不能再使用了。
较新的方法是使用“智能指针”,例如boost :: shared_ptr(如果必须,则使用std :: auto_ptr),而不是指向对象的普通指针。
答案 3 :(得分:1)
是的,它会。
您应该将此功能添加到b
班级:
~b() { delete this->pointer; }
答案 4 :(得分:1)
其他答案都是正确的,您需要添加一个删除pointer
成员的析构函数。我要补充一点,您可能还需要一个复制构造函数和复制赋值运算符来正确处理该指针(Rule of Three)。
另外,我建议您查看智能指针,例如boost::shared_ptr(它将成为C ++ 0x中的std :: shared_ptr)。
答案 5 :(得分:1)
1)是的,它会导致内存泄漏,因为动态分配了a
但从未释放过。{
2)否 - delete t
是不够的,因为t
负责管理/释放自己的资源。
要解决此问题,您需要为b
编写析构函数
即
~b()
{
delete pointer;
}
然而,为了超级安全,你也可以使析构函数虚拟 即。
virtual ~b()
{
delete pointer;
}
这将确保在任何派生类中调用正确的析构函数 HTH
答案 6 :(得分:1)
你不能删除t,这不是指针。您可以在b中使用一个名为“release”的方法,如果需要,可以提前删除指针。在这个例子中,a看起来有点像b的“pImpl”,即它用于在b中实现相同的调用。
正如其他受访者已经正确声明的那样,如果b创建了一个指向new的指针,那么它的析构函数必须删除它,但你需要更多。您需要确保不要复制b也会尝试删除指针。因此,使b不可复制且不可分配。如果它们需要是可复制的或可分配的,则必须重载它们以管理指针。
答案 7 :(得分:0)
从技术上讲,没有内存泄漏,因为程序在暂停完成后退出。程序退出时,将释放由其分配的所有内存。
但当然其他答案都是正确的。 “b”应该有一个析构函数,用于删除“new”分配的内存。
答案 8 :(得分:0)
由于前面提到的类“b”之前的答案应该有一个析构函数来删除构造函数中分配的内存。但是,正如Martin York在上面评论的那样,这不是一个全面的答案。正如他所指出的那样,你需要关注复制构造函数和赋值运算符,但我会更进一步:停止使用原始指针并立即开始使用Boost智能指针。
类“b”被重写为使用boost :: shared_ptr<>:
class b
{
public:
b() { this->pointer.reset(new a); }
void call() { this->pointer->call(); }
private:
boost::shared_ptr<a> pointer;
};
注意两件事:
shared_ptr
会自动销毁它指向的对象(有关条件的更多信息,请参阅相关文档)。pointer
指向的对象的浅层副本足够,我们不必编写显式的复制构造函数或赋值运算符,因为shared_ptr
通过提供自己的“浅拷贝”再次自动处理它“复制构造函数和赋值运算符。即将推出的C ++ 0x标准也有几个智能指针,包括shared_ptr
。另请参阅Boost中的scoped_ptr
以及shared_array
和scoped_array
。最后我发现在处理像Win32这样的C API时特别有用。
答案 9 :(得分:0)
在B类中,您只需在堆栈上创建一个A实例。这减轻了所有权问题。根据我的经验,如果你可以在堆栈上创建成员变量,那么这样做。然后删除是自动的。如果你不能,那么我建议第三方提供指向你B级的指针。提供的指针封装在某种智能指针中。
C ++的一个“问题”是所有权。即谁拥有什么,谁应该删除什么。只有仔细的类设计才能缓解这个问题并减少内存泄漏。
在你有点人为的例子中,B类拥有指向A的指针,因为它是在构造函数中创建的。因此,在此示例中,B类应包含一个删除A实例的析构函数。