【问题标题】:Inconsistency when dereferencing returned empty shared_ptr取消引用时的不一致返回空的 shared_ptr
【发布时间】:2012-09-05 12:00:06
【问题描述】:

我最近注意到在使用返回的空 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 工作。我应该检查返回值是否为空吗?还有其他方法可以返回 null 或空 shared_ptr 吗?如果这很重要,我正在使用 MSVC++ 11...

【问题讨论】:

  • C++ 通常不会在没有用户明确请求的情况下添加昂贵的检查。您可以自行决定将if (pa) 添加到您的代码中。

标签: c++ null return-value shared-ptr dereference


【解决方案1】:

这两种情况下的代码都会取消引用空指针。行为是未定义的,所以任何事情都可能发生,包括看似有意义的事情。不要试图理解它们。未定义就是未定义。

【讨论】:

  • 好的,我明白了——我猜我有点糊涂了。所以在取消引用返回值之前必须进行检查。非常感谢您的回答。
  • @mkh - 没有检查(嗯,正式地,没有理由检查,但没有编译器检查这个)。这就是未定义行为的要点:无需检查,只要发生任何事情就行。
  • @mkh - 哦,对不起,我才意识到你说的是:是的,如果你想访问这个东西,你需要检查一下。
【解决方案2】:

这些示例都没有真正起作用,因为它们使用的是空指针。

在第一种情况下,您实际上没有从 A 访问任何内容,因此您可能不会注意到。在第二种情况下,访问i 成员很可能必须取消引用this 指针(系统会注意到它为空)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-18
    • 2013-09-17
    • 2017-05-02
    • 1970-01-01
    • 2019-06-13
    • 2013-05-21
    • 2016-08-27
    • 2017-03-08
    相关资源
    最近更新 更多