質問

I wonder if placing assert( this != nullptr ); on every member function is a good idea. I believe that the compiler can just decide to ignore this assert entirely, as it is assumed that this cannot be null, so the assert is always true and can be resolved at compile-time.

But if the compiler does not make this assumption, then this assert is pretty useful to catch problems early.

Do compilers assume this?

役に立ちましたか?

解決

No, compilers don't typically assume that. There's even commercial code going around with these checks, some not just asserts but actually logic in them. if (!this) { doSomeWork(); }.

Although you couldn't reach a situation where this would be NULL without running into undefined behavior, if you're well aware of the implementation details then that's a check you can make; and yes, you're right, it can help in debugging.

I wouldn't put it everywhere though. Anywhere, for that matter. If this is indeed NULL, you'll likely get a crash later on when you're accessing some member. If you're not accessing any members, consider marking the method static. It also bloats the code unnecessarily.

他のヒント

Compilers generally only assume anything when optimizations are turned on. So if you compile without optimizations (assert is enabled as long as you don't define NDEBUG, which is independent of optimizations), the assert will work.

It will catch problems with normal methods, but remember that for virtual methods the this pointer is dereferenced in order to even call the method, so the crash already happened before this check is invoked. And for most non-virtual methods the problems won't go unnoticed anyway if the method accesses any members (if it does not, it should not be an instance member function in the first place), so it's question whether adding the assert makes sense.

To addition to what is already said, it makes not sense to test this for nullptr. Even if the pointer is indeed nullptr, this will not always be zero. Here is an example:

#include <iostream>

struct A
{
    void foo() { std::cout << this << std::endl; }
    int a;
};

struct B
{
    void boo() { std::cout << this << std::endl; }
    int b;
};

struct C: public A, public B
{
};

int main()
{
    C *c = 0;
    c->foo(); // this == 0
    c->boo(); // this == 4
    return 0;
}

No it is only necessary to assert it on non-virtual non-static member functions.

On static members, this is forbidden, so ok.

On non-virtual non-static members, as calls are statically determined by the compiler then a call like ptr->f() can be translated to something like f(ptr), so you can have a null this! Strange but possible. So you can assert it.

On virtual members, as calls are dynamically computed, this can never happens. To find the function, it is necessary to dereference the pointer (consult the vtable through the pointer), so the machine will crash at that time (dereferencing a null pointer always crash), just before you can get any chance to make the effective call.

Experiment with this :

#include <iostream>
using namespace std;

struct foo {
  int bar;
  void baz() { bar = 1; }
  void barf() { int i = 5; cout << "barf" << this << endl;}
  virtual void barf2() { int i = 5; cout << "barf2" <<this <<  endl;}
};
int main() {
        struct foo * crash = 0;
        crash->barf(); // do not crash
        crash->barf2(); // crash
        //crash->baz(); // crash
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top