Nullptr and checking if a pointer points to a valid object

前端 未结 2 1431
情歌与酒
情歌与酒 2020-12-13 17:10

In a couple of my older code projects when I had never heard of smart pointers, whenever I needed to check whether the pointer still pointed to a valid object, I would alway

2条回答
  •  无人及你
    2020-12-13 17:48

    In C, anything that's not 0 is true. So, you certainly can use:

    if (ptrToObject) 
        ptrToObject->doSomething();
    

    to safely dereference pointers.

    C++11 changes the game a bit, nullptr_t is a type of which nullptr is an instance; the representation of nullptr_t is implementation specific. So a compiler may define nullptr_t however it wants. It need only make sure it can enforce proper restriction on the casting of a nullptr_t to different types--of which boolean is allowed--and make sure it can distinguish between a nullptr_t and 0.

    So nullptr will be properly and implicitly cast to the boolean false so long as the compiler follows the C++11 language specification. And the above snippet still works.

    If you delete a referenced object, nothing changes.

    delete ptrToObject;
    assert(ptrToObject);
    ptrToObject = nullptr;
    assert(!ptrToObject);    
    

    Because of how long I have been writing these ifs like this, it is second nature at this point to check if the pointers valid before using by typing if (object *) and then calling it's members.

    No. Please maintain a proper graph of objects (preferably using unique/smart pointers). As pointed out, there's no way to determine if a pointer that is not nullptr points to a valid object or not. The onus is on you to maintain the lifecycle anyway.. this is why the pointer wrappers exist in the first place.

    In fact, because the life-cycle of shared and weak pointers are well defined, they have syntactic sugar that lets you use them the way you want to use bare pointers, where valid pointers have a value and all others are nullptr:

    Shared

    #include 
    #include 
    
    void report(std::shared_ptr ptr) 
    {
        if (ptr) {
            std::cout << "*ptr=" << *ptr << "\n";
        } else {
            std::cout << "ptr is not a valid pointer.\n";
        }
    }
    
    int main()
    {
        std::shared_ptr ptr;
        report(ptr);
    
        ptr = std::make_shared(7);
        report(ptr);
    }
    

    Weak

    #include 
    #include 
    
    void observe(std::weak_ptr weak) 
    {
        if (auto observe = weak.lock()) {
            std::cout << "\tobserve() able to lock weak_ptr<>, value=" << *observe << "\n";
        } else {
            std::cout << "\tobserve() unable to lock weak_ptr<>\n";
        }
    }
    
    int main()
    {
        std::weak_ptr weak;
        std::cout << "weak_ptr<> not yet initialized\n";
        observe(weak);
    
        {
            auto shared = std::make_shared(42);
            weak = shared;
            std::cout << "weak_ptr<> initialized with shared_ptr.\n";
            observe(weak);
        }
    
        std::cout << "shared_ptr<> has been destructed due to scope exit.\n";
        observe(weak);
    }
    

    Now, will C++ do the same for pointers? If pass in a char * like this to an if statement?

    So to answer the question: with bare pointers, no. With wrapped pointers, yes.

    Wrap your pointers, folks.

提交回复
热议问题