为什么不为C++提供DELETE宏的原因

moa*_*ala 17 c++ macros pointers memory-management

有没有什么好的理由(除了"宏是邪恶的",也许)不使用以下宏?

#define DELETE( ptr ) \
if (ptr != NULL)      \
{                     \
    delete ptr;       \
    ptr = NULL;       \
}

#define DELETE_TABLE( ptr ) \
if (ptr != NULL)            \
{                           \
    delete[] ptr;           \
    ptr = NULL;             \
}
Run Code Online (Sandbox Code Playgroud)

Goz*_*Goz 42

我个人更喜欢以下

template< class T > void SafeDelete( T*& pVal )
{
    delete pVal;
    pVal = NULL;
}

template< class T > void SafeDeleteArray( T*& pVal )
{
    delete[] pVal;
    pVal = NULL;
}
Run Code Online (Sandbox Code Playgroud)

他们最终编译成完全相同的代码.

可能有一些奇怪的方法你可以打破#define系统,但是,个人(这可能会让我呻吟;)我不认为这是一个很大的问题.

  • @CătălinPitiş:我会将其重命名为DeleteAndNullify,以便在不阅读文档的情况下更加清晰.而且因为"安全"没有说明为什么它是安全的. (10认同)
  • 因为RAW指针应该包含在一个类中以保护它们的破坏通常发生在析构函数中.此时,对NULL的额外赋值变得多余. (10认同)
  • 实际上,由于像DELETE(ptr ++)这样的错误,因此宏更安全. (8认同)

CB *_*ley 30

因为它实际上并没有解决很多问题.

实际上,大多数悬空指针访问问题来自这样一个事实:在程序的其他地方存在另一个指向同一对象的指针,后来用于访问已删除的对象.

将未知数量的指针副本中的一个归零可能会有所帮助,但通常这是一个指针即将超出范围,或者设置为指向任何情况下的新对象.

从设计的角度来看,手动调用delete还是delete[]比较少见的.按价值计算,而不是在那里appropriatem使用动态分配的对象使用的对象std::vector,而不是动态分配数组,并包裹有以适当的智能指针动态分配对象的所有权(如auto_ptr,scoped_ptrshared_ptr)来管理他们的一生都设计方法,使更换delete并且delete[]"更安全"的宏观是一种相对较低的收益方法.


Ara*_*raK 16

因为可以删除NULL(0)指针.无需检查指针是否实际NULL(0)存在.如果要将指针设置为NULL,则在删除之后,可以在delete不使用宏的情况下全局重载运算符.


关于第二点我似乎错了:

如果要将指针设置为NULL,则在删除之后,可以delete全局重载运算符

问题是,如果你超载全球newdelete,你可以有这样的事情:

void* operator new(size_t size)
{
    void* ptr = malloc(size);

    if(ptr != 0)
    {
        return ptr;
    }

    throw std::bad_alloc("Sorry, the allocation didn't go well!");
}

void operator delete(void* p)
{
    free(p);
    p = 0;
}
Run Code Online (Sandbox Code Playgroud)

现在,如果你设置p = 0;了重载delete,你实际上是设置local一个,而不是原始p.基本上,我们在重载中获得指针的副本delete.

对不起,这是我的头脑,我现在再考虑一下.无论如何,我会写模板内联函数来做事而不是写EVIL MACROS :)

  • 我有兴趣看看你如何重载删除并将指针设置为null,你能添加例子吗?当您重载"operator delete"时,您会按值获取指针,因此将其设置为null将不会修改原始调用中使用的指针.目前你有'+1',因为"不需要检查空指针",但是'-1'表示你可以重载操作符删除并做同样的事情. (3认同)

moa*_*ala 13

因为已经在winnt.h中定义了DELETE:

#define DELETE(0x00010000L)

  • +1:现在有一个不使用宏命名空间污染的真正原因.我想象`DELETE`也可以出现在其他地方. (5认同)

APr*_*mer 9

  • 删除接受一个没有问题的NULL指针,所以测试是多余的.
  • 将指针重置为NULL并不总是可行的,因此不能系统地使用它们.
  • 他们带来的安全性是虚幻的:根据我的经验,大多数悬空指针问题来自除了用于删除的指针之外的指针.

  • 指针可能不是左值:DELETE(some_function()) (9认同)
  • 你能解释一下你的语句"将指针重置为NULL并不总是可行"吗? (4认同)
  • 如果指针是"const",则无法将其重置为"NULL". (4认同)

jal*_*alf 5

您的宏失败有几个原因:

  • 这是一个宏.它不尊重范围规则或许多其他语言功能,使其易于使用不正确.
  • 它可能导致编译错误:DELETE (getPtr());无法编译,因为您无法将函数调用设置为null.或者如果指针是const,您的宏也将失败.
  • 它什么都没做.delete NULL是标准允许的.

最后,正如克里姆纳所说,你正试图解决一个本来就不存在的问题.你为什么要手动调用删除?`你不使用标准库容器吗?智能指针?堆栈分配?RAII?

正如Stroustrup之前所说,避免内存泄漏的唯一方法是避免必须调用delete.