null shared_ptr可以访问成员函数

tun*_*unc 1 c++ tr1 shared-ptr c++11

我可以访问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;
}
Run Code Online (Sandbox Code Playgroud)

当我期待一个例外时返回1234.同样的结果发生了

std::shared_ptr<A> pA();
Run Code Online (Sandbox Code Playgroud)

要么

std::shared_ptr<A> pA();
pA.reset();
Run Code Online (Sandbox Code Playgroud)

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

使用VS2010.

How*_*ant 9

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

5 要求:get() != 0.

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

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


Rap*_*ien 7

完整的答案在这里:

何时在null实例上调用成员函数会导致未定义的行为?

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


zwo*_*wol 6

从技术上讲,你在这里所做的事情确实需要未定义的行为.但是,因为你的getNum方法不是virtual并且没有任何用处this,所以这次碰巧不会崩溃.要了解原因,请想象编译器在内部重写了您的程序,如下所示:

class A { };

int A_getNum(A* this) { return 1234; }

int main()
{
  A* pA = 0;
  std::cout << A_getNum(pA) << '\n';
}
Run Code Online (Sandbox Code Playgroud)

您可以看到,即使没有实际对象,也永远不会取消引用空指针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
Run Code Online (Sandbox Code Playgroud)

抱歉,无法帮助您使用MSVC.