Bo Yang :
I am sorry, I have paste the wrong code here.
the variable r is a reference in my brain, I mean
the following code:
#include <iostream>
class Test{
public:
Test(){};
void print(){ std::cout << "OK" << std::endl ; };
};
int main( int argc , char ** argv ){
Test * test = new Test();
Test& r = *test ;
delete test ;
r.print(); //this line , this line
}
You know, the reference r has reference to nothing
when the test object to be deleted. So, why the program
run normally whiout a crash!
Because you don't try to access any of it's members (methods are not
members of the instance, but of the class). As Salt_Peter pointed out in
another post, if you try to access a member it will most probably crash.
Change Test to this and try again (don't forget to #include <string>):
class Test {
private:
std::string text;
public:
Test() : text("OK") {}
void print() { std::cout << text << std::endl; }
};
The reason is that when you declare a class like this what really
happens is that the print-method get an additional parameter added by
the compiler. So print acctually looks like this:
void print(Test* t) { ... }
And when you call print on an instance of Test like this:
Test t;
t.print();
It's converted to this:
Test t;
print(&t);
Now, if print looks like above:
void print() { std::cout << text << std::endl; }
This is then converted to
void print(Test* t) { std::cout << t->text << std::endl; }
As you can see, you can thus call any method on any pointer to Test as
long as the method does not actually try to access any of the class's
members, but when you do you have a problem. Of course you could write
code that try to access a member even if it's not needed just to avoid
things like those, but there's really no benefit (it would only slow
things down).
Disclaimer: I don't claim that this is the way things work, but it's a
good way of thinking about it. Different compilers might do things
differently.