【问题标题】:null shared_ptr can access to member functionsnull shared_ptr 可以访问成员函数
【发布时间】:2011-04-05 01:31:38
【问题描述】:

我可以访问一个空的 shared_ptr 对象的成员函数:

#include <memory>
#include <iostream>

class A
{
public:
    int getNum() {return 1234;}
};

int main()
{
    std::shared_ptr<A> pA(nullptr);
    std::cout << pA->getNum() << std::endl;
}

在我期待异常时返回 1234。同样的结果发生在

std::shared_ptr<A> pA();

std::shared_ptr<A> pA();
pA.reset();

这真的是预期的行为吗? 如果是在成员函数调用的情况下引发异常的 corect shared_ptr 定义是什么?

使用 VS2010。

【问题讨论】:

    标签: c++ c++11 shared-ptr tr1


    【解决方案1】:

    shared_ptr 上调用 operator-&gt;() 需要 [util.smartptr.shared.obs]:

    5 需要get() != 0

    这意味着如果get() == 0 当您调用operator-&gt;() 时,您会得到未定义的行为。未定义的行为意味着任何事情都可能发生:您可能会遇到异常。您可以获得预期的结果(无论是什么)。您可以备份最近的主要城市的所有厕所。就是不知道。

    无论您的实现如何处理这段代码,实现都是正确的。

    【讨论】:

      【解决方案2】:

      完整答案在这里:

      When does invoking a member function on a null instance result in undefined behavior?

      简短的回答是,是的,这是未定义的行为(或者,至少,在规范中没有明确定义),并且实际行为并非不合理,因为它静态地知道类型并且不引用到其中的任何数据。然而,指望这种行为几乎肯定不是一个好主意。

      【讨论】:

        【解决方案3】:

        从技术上讲,您在此处所做的确实会导致未定义的行为。但是,因为您的getNum 方法不是virtual 并且没有使用任何this,所以这次它恰好不会崩溃。要了解原因,假设编译器在内部重写了您的程序,如下所示:

        class A { };
        
        int A_getNum(A* this) { return 1234; }
        
        int main()
        {
          A* pA = 0;
          std::cout << A_getNum(pA) << '\n';
        }
        

        您可以看到,即使没有实际的A 对象,空指针也永远不会取消引用,因此它不会崩溃。 shared_ptr 无关紧要——如果你使用裸指针,你会得到同样的效果。

        如果你想强制 shared_ptr-&gt; 用于空指针时让你崩溃,嗯,我不相信有什么标准。不过,您的编译器可能有一个可以打开的调试选项——例如,如果我使用 gcc 4.5 和-D_GLIBCXX_DEBUG 编译您的程序,我会得到

        $ ./a.out 
        /usr/include/c++/4.5/bits/shared_ptr_base.h:710: 
        _Tp* std::__shared_ptr<_Tp, _Lp>::operator->() const 
        [with _Tp = A, __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]: 
        Assertion '_M_ptr != 0' failed.
        Aborted
        

        在 MSVC 方面无法为您提供帮助,抱歉。

        【讨论】:

          猜你喜欢
          • 2016-02-17
          • 2013-05-03
          • 1970-01-01
          • 2016-03-08
          • 2014-07-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-05-06
          相关资源
          最近更新 更多