I can access member functions of a null shared_ptr object :
#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;
}
returns 1234 while I was expecting an exception. Same result happens for
std::shared_ptr<A> pA();
or
std::shared_ptr<A> pA();
pA.reset();
Is this really the expected behaviour ? If it is what is the corect shared_ptr defination that throws an exception in case of a member function call ?
Using VS2010.
Calling operator->()
on a shared_ptr
requires [util.smartptr.shared.obs]:
5 Requires:
get() != 0
.
This means that if get() == 0
when you call operator->()
, you get undefined behavior. Undefined behavior means anything can happen: You could get an exception. You could get your expected result (whatever that is). You could back up all of the toilets in the closest major city. There's just no telling.
No matter what your implementation is doing with this code, the implementation is correct.
The full answer is here:
When does invoking a member function on a null instance result in undefined behavior?
The short answer is that, yes, this is undefined behavior (or, at least, is not unambiguously defined in the spec), and that the actual behavior is not unreasonable given that it knows the type statically and doesn't refer to any data within it. However, counting on this behavior is almost certainly not a good idea.
Technically, what you did here does entail undefined behavior. However, because your getNum
method is not virtual
and makes no use whatsoever of this
, it happens not to crash this time. To see why, imagine that the compiler internally rewrote your program like so:
class A { };
int A_getNum(A* this) { return 1234; }
int main()
{
A* pA = 0;
std::cout << A_getNum(pA) << '\n';
}
You can see that the null pointer is never dereferenced even though there is no actual A
object, so it doesn't crash. The shared_ptr
is irrelevant -- you'd get the same effect if you'd used a bare pointer.
If you want to force shared_ptr
to crash you whenever ->
is used on a null pointer, um, I don't believe there's anything standard. Your compiler may have a debugging option you can turn on, though -- for instance, if I compile your program with gcc 4.5 and -D_GLIBCXX_DEBUG
, I get
$ ./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
Can't help you with MSVC, sorry.
精彩评论