51

在我从未听说过智能指针的几个旧代码项目中,每当我需要检查指针是否仍然指向有效对象时,我总是会做这样的事情......

object * meh = new object;
if(meh) 
    meh->member;

或者当我需要安全地删除对象时,像这样

if(meh)
{
    delete meh;
    meh = 0;
}

好吧,现在我已经了解了在布尔表达式中使用对象和指针可能产生的问题,这两种方法都带有文字数字,很难:。现在,我还了解到了 C++ 中一个不那么新但非常酷的特性,即nullptr关键字。但现在我很好奇。

我已经完成并修改了我的大部分代码,例如,在删除我现在编写的对象时

if(meh)
{
    delete meh;
    meh = nullptr;
}

现在我想知道布尔值。当你把一个 int 说成这样的 if 语句时,

int meh;
if(meh)

然后它会隐式检查零,而无需您编写它。

if(meh == 0) // does the exact same check

现在,C++ 会为指针做同样的事情吗?如果将这样的 char * 传递给 if 语句?

char * meh;
if(meh)

那么它会隐含地将它与nullptr进行比较吗?由于我已经像这样编写这些 if 有多久了,此时通过键入 if (object *) 然后调用其成员来检查指针是否有效在这一点上是第二天性。如果这不是功能,为什么不呢?实施起来太难?将通过删除另一种可能会弄乱代码的小方法来解决一些问题。

4

2 回答 2

55

在 C 中,任何不为 0 的都是真的。所以,你当然可以使用:

if (ptrToObject) 
    ptrToObject->doSomething();

安全地取消引用指针。

C++11 稍微改变了游戏,nullptr_t它的类型nullptr是实例;的表示nullptr_t是特定于实现的。因此,编译器可以随心所欲地定义nullptr_t。它只需要确保它可以对 anullptr_t到不同类型的强制转换实施适当的限制——允许使用布尔值——并确保它可以区分 anullptr_t和 0。

只要编译器遵循 C++11 语言规范,Sonullptr就会正确且隐式地转换为布尔值。 false上面的代码片段仍然有效。

如果删除引用的对象,则不会发生任何变化。

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

由于我已经像这样编写这些 if 有多久了,此时通过键入 if (object *) 然后调用它的成员来检查指针是否在使用之前有效是第二天性。

,请保持正确的对象图(最好使用唯一/智能指针)。正如所指出的,没有办法确定一个不是nullptr指向有效对象的指针。无论如何,您有责任维护生命周期。这就是指针包装器首先存在的原因。

事实上,由于共享指针和指针的生命周期定义明确,它们具有语法糖,可让您以您希望使用裸指针的方式使用它们,其中有效指针具有值,而所有其他指针是nullptr

共享

#include <iostream>
#include <memory>

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

int main()
{
    std::shared_ptr<int> ptr;
    report(ptr);

    ptr = std::make_shared<int>(7);
    report(ptr);
}

虚弱的

#include <iostream>
#include <memory>

void observe(std::weak_ptr<int> 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<int> weak;
    std::cout << "weak_ptr<> not yet initialized\n";
    observe(weak);

    {
        auto shared = std::make_shared<int>(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);
}

现在,C++ 会为指针做同样的事情吗?如果将这样的 char * 传递给 if 语句?

所以回答这个问题:用指针,没有. 使用包装的指针,的。

伙计们,把你的指针包起来。

于 2012-07-01T05:08:35.437 回答
14

无法测试指针是否指向有效对象。如果指针不为空但未指向有效对象,则使用指针会导致未定义的行为。为了避免这种错误,你有责任小心被指向的对象的生命周期;智能指针类有助于完成这项任务。

如果是原始指针,则and和meh之间没有任何区别。如果指针不为空,它们都会继续进行。if (meh)if (meh != 0)if (meh != nullptr)

存在从文字0到的隐式转换nullptr

于 2014-09-08T00:25:08.527 回答