由c++类指针未初始化引发的“思考”

C++ 类指针定义的时候没有初始化的时候,居然可以安全的调用类内部的成员函数而不出错。
image

结果是输出A。
Google一通得出的结论是:初始化为NULL的类指针可以安全调用不涉及类成员变量的类成员函数而不出错,但是如果类成员函数中调用了类成员变量则会出错,既然赋值为NULL的情况都可以使用,那么自然不初始化的类指针同样满足这类情况。

假设现在有一个简单的类定义如下:

class Test
{
public:
    void func(){cout << "hahaha" << endl;}
    int get(){return a+b;}
    Test():a(1),b(2){}
public:
    int a,b;
};

而之后编译器会自动将这个类转换成:

class Test
{
    int a,b;
};
void _test_func(Test * this);
int _test_get(Test* this);
........

类中的函数被编译器静态编译了,所有非虚函数(虚函数呢?别急,待会会解释到)都可以调用,因为函数地址在编译期间已经确定。我们知道,类中的成员函数都是通过this指针调用成员变量的,编译器会将this指针作为默认参数传给类成员函数的,如myclass.function(int a,int b) --> function(&myclass,int a,int b)
好,现在我们添加main函数如下:

int main()
{
    Test *p=NULL;
    p->func();//正确,没有调用成员变量,没有使用空的this指针
    p->get();//错误,this指针为空,通过this指针调用变量所以出错
    return 0;
}

运行结果见上面注释,没有调用成员变量的func()函数正确执行,调用了成员变量的get()函数错误。两者其实都传入了空的this指针,前者没出错仅仅是因为没有调用this指针,而后者调用了。调用成员函数的时候,函数地址是编译期间确定的,成员函数不通过对象指针(也即当前的p指针)去调用,对象指针仅仅作为参数传入函数然后去调用成员变量。

那如果是虚函数呢,因为虚函数要通过this指针计算vptr,然后找到vtable,然后dispatch。因为this指针为空,所以在找vtable时候就会coredump了。总之这类情况下,一切调用了this指针的函数都会出错,而完全不调用this指针的成员函数则没问题。
GDB调试
总结一下:

成员函数在静态编译的时候地址已经确定,调用的时候直接通过函数地址调用,this指针只是参数传入,p->get()也一样,只不过其内部调用了空的this指针来调用成员变量,所以出错。

再补充一个知识点:

类在实例化对象后,对象占内存的大小,是取决于类里的非静态数据成员。类的 静态数据成员非静态成员函数静态成员函数,都不会影响对象所占内存空间的大小。

这是为啥呢?
就像我们刚刚看到,因为静态数据成员是属于整个类的,为该类的每个对象所共有的,每个对象用到的静态成员变量,其实同一个东西;
而非静态成员函数呢?其实也是属于类的,每个该类的对象,调用的非静态成员函数,其实也都是同一个的,那为啥同一类的不同对象调用某一个非静态成员函数会得到不同的结果呢?因为this指针哈!this指针使得不同对象调用同一个函数,也可以得到不一样的结果。

感谢http://longzxr.blog.sohu.com/213486896.html

你可能感兴趣的:(由c++类指针未初始化引发的“思考”)