我可以访问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。
答案 0 :(得分:9)
在operator->()
上调用shared_ptr
需要[util.smartptr.shared.obs]:
5 需要:
get() != 0
。
这意味着如果在调用get() == 0
时operator->()
,则会出现未定义的行为。未定义的行为意味着任何事情都可能发生:您可能会遇到异常。你可以得到你期望的结果(不管是什么)。你可以备份最近的主要城市的所有厕所。没有什么可说的。
无论您使用此代码执行什么操作,实现都是正确的。
答案 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,抱歉。