代码之家  ›  专栏  ›  技术社区  ›  yesraaj

在删除之前,是否有任何理由检查NULL指针?

  •  56
  • yesraaj  · 技术社区  · 17 年前

    NULL 在删除指针之前,

    if (NULL != pSomeObject) 
    {
        delete pSomeObject;
        pSomeObject = NULL;
    }
    

    空值 空值

    10 回复  |  直到 11 年前
        1
  •  72
  •   Randolpho    5 年前

    删除空指针是完全“安全”的;这实际上相当于无行动。

    编辑

    备注 delete NULL

        2
  •  40
  •   Konrad Rudolph    7 年前

    C++标准保证在 删除表达式 (§8.5.2.5/2).然而,事实确实如此 这是否会调用取消分配函数( operator delete operator delete[] §8.5.2.5/7,注释)。

    但是,如果标准库没有提供释放函数,会发生什么,也就是说,当我们重载时会发生什么 运算符delete (或

    一个称职的程序员会相应地处理空指针 释放函数,而不是在调用之前,如OP代码所示。同样,将指针设置为 nullptr / NULL defensive programming

    您应该将重置指针视为代码气味。

    运算符delete :

    运算符delete 是(尽管它的名字)一个可以像任何其他函数一样重载的函数。每次调用时,都会在内部调用此函数 运算符delete 与匹配的参数。这同样适用于 operator new .

    过载 new操作 运算符delete 有效C++ .

    目前,我们只想让全球版本的 new操作

    klass* pobj = new klass;
    // … use pobj.
    delete pobj;
    

    // 1st step: allocate memory
    klass* pobj = static_cast<klass*>(operator new(sizeof(klass)));
    // 2nd step: construct object in that memory, using placement new:
    new (pobj) klass();
    
    // … use pobj.
    
    // 3rd step: call destructor on pobj:
    pobj->~klass();
    // 4th step: free memory
    operator delete(pobj);
    

    请注意我们调用的步骤2 new 安置 它获取一个地址并在该地址构造一个对象。此运算符也可能过载。在这种情况下,它只是用来调用类的构造函数 klass .

    现在,闲话少说,这是运算符重载版本的代码:

    void* operator new(size_t size) {
        // See Effective C++, Item 8 for an explanation.
        if (size == 0)
            size = 1;
    
        cerr << "Allocating " << size << " bytes of memory:";
    
        while (true) {
            void* ret = custom_malloc(size);
    
            if (ret != 0) {
                cerr << " @ " << ret << endl;
                return ret;
            }
    
            // Retrieve and call new handler, if available.
            new_handler handler = set_new_handler(0);
            set_new_handler(handler);
    
            if (handler == 0)
                throw bad_alloc();
            else
                (*handler)();
        }
    }
    
    void operator delete(void* p) {
        cerr << "Freeing pointer @ " << p << "." << endl;
        custom_free(p);
    }
    

    malloc / free

    int main() {
        int* pi = new int(42);
        cout << *pi << endl;
        delete pi;
    }
    

    它产生了以下输出:

    Allocating 4 bytes of memory: @ 0x100160
    42
    Freeing pointer @ 0x100160.
    

    现在,这段代码做了一些与标准实现根本不同的事情 运算符delete :

    然而,正如我之前所说,这种行为实际上是出乎意料的,而且是图书馆作家 应该 请注意检查 运算符delete

    void operator delete(void* p) {
        if (p == 0) return;
        cerr << "Freeing pointer @ " << p << "." << endl;
        free(p);
    }
    

    运算符delete 可能需要在客户端代码中进行显式的空检查,这是非标准行为,只应在遗留支持中被容忍( 如果有的话

        3
  •  9
  •   Welbog    17 年前

    如果指针为空携带了您关心的其他信息,您可能会出于其他原因检查空。

        4
  •  9
  •   EvilTeach    17 年前

        5
  •  4
  •   Lingxi    14 年前

    根据C++035.3.5/2,删除空指针是安全的。

        6
  •  3
  •   Joe    16 年前

    如果pSomeObject为NULL,delete将不会执行任何操作。所以,不,你不必检查NULL。

    我们认为,如果某个傻瓜有可能尝试使用指针,那么在删除指针后为其分配NULL是一种很好的做法。使用NULL指针比使用指向未知内容的指针稍好(NULL指针会导致崩溃,指向已删除内存的指针可能不会)

        7
  •  1
  •   VoidPointer    17 年前

    在删除之前没有理由检查NULL。 如果在代码的某个地方通过执行NULL检查来检查是否已经分配了某些对象,那么在删除后分配NULL可能是必要的。一个例子是按需分配的某种缓存数据。每当清除缓存对象时,都会将NULL分配给指针,以便分配对象的代码知道它需要执行分配。

        8
  •  0
  •   Joe Pineda    17 年前

    我相信之前的开发人员对其进行了“冗余”编码,以节省一些毫秒:

    if(pSomeObject1!=NULL) pSomeObject1=NULL;
    

    因此,我敢打赌,这些行的作者试图确保pSomeObject1在删除后始终为NULL,而不会产生潜在的不必要的测试和分配成本。

        9
  •  -2
  •   Hosam Aly    17 年前

    free NULL 指针。一些图书馆仍然存在这个问题。例如, XFree 在Xlib库中说:

    描述

    释放指定的数据。你必须 用它来释放任何物体 函数已明确指定 物体。NULL指针不能 传递给此函数。

    所以考虑解放 空值 把指针当作bug,你就安全了。

        10
  •  -5
  •   aaaa aaaa    16 年前