我知道当我使用new初始化指针时,我需要删除指针或发生内存泄漏。我有一个这样设置的课程:
class foobar
{
private:
//! Pointer to the global nodal list
int *p_test1;
//! Pointer to the global block label list
int *p_test2;
public:
foobar(int *test1, int *test2)
{
p_test1 = test1;
p_test2 = test2;
}
~foobar()
{
delete p_test1;
delete p_test2;
}
};
现在,当调用析构函数时,程序崩溃,控制台显示程序已退出,返回码为-6。
调试窗口指出:
程序接收信号SIGABRT
当我通过调用堆栈时,最后一项是析构函数。堆栈似乎试图释放内存但失败了。
我想知道为什么会这样?使用类设置释放内存的首选方法是什么。
作为旁注,如果我在析构函数中注释掉代码,那么当foobar类的实例完成时,指针当然不会被释放。但是,当我调用该类的另一个实例时(假设用户按下GUI上的按钮来指定实例的创建),则程序崩溃。再次,这是为什么?我觉得这与没有正确销毁指针有关。
答案 0 :(得分:2)
正如评论中所提到的,此示例中没有新内容,因此很难解释new
和delete
之间的平衡。
规则是如果你新建了一个指针,你应该删除它。
int * p = new int( 5 );
std::cout << "The value of p is " << *p << std::endl;
delete p;
但是,如果您使用某个对象,因为您没有使用该对象,则不应该(通常)将其删除。
void somefunction( int * p )
{
std::cout << "The value of p is " << *p << std::endl;
delete p; // this looks smelly - deleting a pointer which was allocated.
}
为了尝试简化这个问题(我应该删除哪些指针),现代C ++有一些很好的指导。
RAII将资源投入课堂。完整的类(与指针相对)具有非常清晰的生命周期。当它因为超出范围而被销毁时,则会调用析构函数。
class PointerHolder {
int * mp;
public:
PointerHolder( int value ) : mp( NULL) {
mp = new int( value );
}
~PointerHolder() {
delete mp;
}
}
虽然上面的例子打破了5的规则。
上面的PointerHolder问题是它没有实现所有5个特殊运算符。
PointerHolder a( 12 );
PointerHolder b( 10 );
a = b; // What is going to happen?????
a获取b指针的值,当第二个被销毁时,它是同一块内存的第二次删除,程序崩溃。
5个州的规则,如果您实施destructor
,move operator
,copy constructor
或operator =
您应该实施(或删除所有这些)
在这种情况下,删除移动和复制操作符会产生一个简单的unique_ptr
。
零规则是,如果一个类实现了所有运算符,或者没有一个运算符,那么它就更可重用。
如果您只需要实施某些运营商,很可能您尚未确定&#34;资源&#34; - 应该是一个包含所有5个重载运算符的单个类。
从C ++ 11开始,使用new和delete,被认为仅限于库编写者。由于使用std::shared_ptr
和std::unique_ptr
为您管理new
delete
生命周期,因此您可以专注于手头的问题。