返回空的shared_ptr解引用时不一致

3

最近我注意到使用返回的空 shared_ptr 时存在一些奇怪的行为。为了说明问题,考虑以下示例:

    struct A {
      A() { }
      void foo() {
        std::cout << "A::foo" << std::endl;
      }
    };

    struct B {
      B() :i(42) { }
      void foo() {
        std::cout << "B:foo with i: " << i << std::endl;
      }

      int i;
    };

    template<typename T>
    std::shared_ptr<T> create_empty() {
      return std::shared_ptr<T>(); 
    }

然后调用:
    std::shared_ptr<A> pa(create_empty<A>());
    pa->foo(); // #1: Works fine and prints: "A::foo".

    std::shared_ptr<B> pb(create_empty<B>());
    pb->foo(); // #2: Throws an exception.

现在我的问题是,为什么调用#1有效(我也预期会得到异常),如果这是正确的行为,如何防止#1有效。我是否应该检查返回值是否为空?还有其他方法可以返回空或空的shared_ptr吗?如果这很重要,我正在使用MSVC++ 11...


C++通常不会在没有用户明确请求的情况下添加昂贵的检查。您完全可以自行决定在代码中添加if (pa) - Kerrek SB
2个回答

3

这两种情况下的代码都会取消引用一个空指针,由于行为是未定义的,所以任何事情都可能发生,包括看起来有道理的事情。不要试图从中寻找意义。未定义就是未定义。


好的,我明白了 - 我有点困惑。因此,在取消引用返回值之前必须进行检查。非常感谢您的答案。 - mkh
@mkh - 没有检查(好吧,正式上讲,没有理由进行检查,但是没有编译器会检查这个)。这就是未定义行为的要点:不需要检查它,只需让任何事情发生。 - Pete Becker
@mkh - 哦,抱歉,我刚才才明白你的意思:是的,如果你想访问这个东西,你需要检查。 - Pete Becker

1

这些示例都不起作用,因为它们使用了空指针。

在第一个案例中,您实际上并没有从 A 中访问任何内容,因此您可能不会注意到。在第二个案例中,访问 i 成员极有可能需要对 this 指针进行解引用(并且系统将注意到它为空)。


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