null shared_ptr可以访问成员函数

时间:2011-04-05 01:31:39

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

我可以访问null 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 defination在成员函数调用的情况下抛出异常是什么?

使用VS2010。

3 个答案:

答案 0 :(得分:9)

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

  

5 需要get() != 0

这意味着如果在调用get() == 0operator->(),则会出现未定义的行为。未定义的行为意味着任何事情都可能发生:您可能会遇到异常。你可以得到你期望的结果(不管是什么)。你可以备份最近的主要城市的所有厕所。没有什么可说的。

无论您使用此代码执行什么操作,实现都是正确的。

答案 1 :(得分:7)

完整的答案在这里:

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

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

答案 2 :(得分:6)

从技术上讲,你在这里做的确实需要未定义的行为。但是,由于您的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在空指针上使用->时崩溃,嗯,我不相信有任何标准。您的编译器可能有一个可以打开的调试选项 - 例如,如果我使用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,抱歉。