释放内存时是否需要使用IF语句?

5

我希望理解C++中的内存部分。我想在使用下面的代码生成输出后释放内存。

问题:

使用if语句释放内存是否必要?

代码:

int main(){
    char *pc;
    int *pi;

    pc = new char('a');
    pi = new int(8);

    cout << *pc << endl;
    cout << *pi << endl;

    //What's the purpose for doing if(pc) and if (pi) below?

    if(pc){
        delete pc;
    }
    if(pi){
        delete pi;
    }

return 0;
}

我能用这种方式吗? int main(){ char *pc; int *pi;

    pc = new char('a');
    pi = new int(8);

    cout << *pc << endl;
    cout << *pi << endl;


    delete pc;
    delete pi;

return 0;
}

8
不需要,删除操作会自行执行空值检查。请参考此链接 -> https://dev59.com/MW855IYBdhLWcg3wsWv3#4190737 - user1898811
4
必要的智能指针参考。如果你使用它们,就不必担心任何这些问题。 - chris
3个回答

9

释放内存时是否需要使用IF语句?

不需要,只要您没有覆盖全局的operator delete,这样做是完全可以的,什么也不会发生:

int* p = nullptr;
delete p;

根据C++11标准的第3.7.4/2段:

[...] 提供给释放函数的第一个参数的值可以是空指针;如果是这样,并且释放函数是标准库中提供的,则调用不会有任何效果。 [...]

正如评论中chris所建议的那样,请考虑使用智能指针而不是通过原始指针、newdelete(或其数组对应项)执行手动内存管理。


那其实不太好:http://ideone.com/ee9VS1 - Ben Voigt
@BenVoigt:嗯,这不是一个bug吗?我期望根据5.3.5/1-2,nullptr会在上下文中被转换为指针类型。 - Andy Prowl
根据代码,我更喜欢检查或断言NULL,因为它可能指向错误条件。但是释放NULL是安全的。 - Michael Dorgan
2
此外,std::nullptr_t 不是类类型,因此上下文隐式转换不适用。(即使它适用,也会产生歧义) - Ben Voigt
2
@BenVoigt:嗯,没错 :) 谢谢,今天学到了东西。 - Andy Prowl
如果有帮助的话,delete 0;delete NULL; 也是不正确的。 - Ben Voigt

3

在你的代码中,不需要进行空指针检查。

一般来说,delete (T*)0; 是否会调用类型 T 的释放函数取决于实现。如果你的实现将null指针传递给了释放函数,并且你的类型已经提供了成员 operator delete,或者你提供了一个替代全局 ::operator delete 并且该自定义释放函数不能很好地处理空指针值,那么你可能会遇到问题。

标准并不要求自定义的 operator delete 在接收到空指针时什么也不做。它不应该执行失败操作,但它可能会写入不良日志消息或告诉你的老板有人没有遵守编码规范等。


+1 提到自定义删除 - Steve
@Ming: 它不能将不同的指针传递给释放函数。如果你写了 delete (p),而 p 是空指针,那么编译器要么会调用 operator delete(p) 要么什么也不做。如果 p 不是空指针,那么编译器肯定会先调用析构函数,然后再调用 operator delete(p) - Ben Voigt
@BenVoigt 所以在这种情况下,我只需要执行 delete(pc); delete(pi) 就可以了,是吗? - 14K
1
@Ming:你肯定可以执行delete pc; delete pi;,因为它们在第一时间就不可能为空。 - Ben Voigt
有时候你会有一个变量,它可能是空的,也可能不是。但是你的变量不能是空的。 - Ben Voigt
显示剩余2条评论

-1

不是必须的,但这被认为是一种良好的实践。在现实生活中,由于业务需求、错误等原因,您的代码经常发生变化,因此最好使用这种防御性编程策略。

你最不想看到的是因为同事更改了代码的上部而导致释放已经释放的指针而产生难以检测的错误。


2
忘记这个检查不会导致双重释放。它只会导致释放空指针。这什么也不做。 - djechlin
1
它并没有防御任何东西。 - djechlin
1
基本上,这是C编程的遗留物,在C中是一种良好的实践。但在C++中,除了让代码看起来更像C语言之外,它没有任何作用。我不认为这是一种良好的实践,也不认识任何人认为是;对我来说,所有这些看起来只是由一个不理解C++或者懒得学习语言和编码风格的人编写的C代码。 - djechlin
1
在释放指针后将其设置为null会给人一种虚假的安全感。int *p = new int; int *q = p; delete p; p = 0;现在,if(q)也无法帮助。正确处理指针和内存管理的代码是你设计的内容,而不是因为某个规范要求你这样做。"防御性"编程不能替代良好的设计。 - Pete Becker
“这被认为是一种良好的实践” - 我从未听说过这被称为“良好的实践”(好吧,现在我知道了)。而检查 nullptr 是否会检测到双重释放(提示:不会)? - Christian Rau
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接