今天看见一道面试题,比较有意思,这一分享出来:
1.下面程序能编译通过吗?
2.下面程序会崩溃吗?在哪里崩溃
class A
{
public:
void PrintA()
{
cout<<_a<<endl;
}
void Show()
{
cout<<"Show()"<<endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->PrintA();
p->Show();
}
这道题是对C++语法基础的考察,主要考察我们对于this指针和空指针的理解掌握。
在解答之前,我们先对这两个知识点复习一下:
- this指针
- this指针类型:类的类型 *const
- this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
- this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递
- 空指针
当我们初始化一个空指针之后,比如
int *a = nullptr;
此时空指针会造成内存泄漏?显然不会,当我企图对空指针指向空间内的数据时,此时才会造成野指针错误,简单来说,就是对空指针的解引用是不能接受的。
此时,我们可以解答这题了:
由于我们将A实例化为一个空指针对象,所以此时this指向该对象,也为空指针.(原因在于this是成员函数的第一个形参,类对象指针需要作为实参被隐式传递给形参)
之前我们说过,只要不对空指针进行解引用就不会造成错误,那么答案很简单,PrintA函数试图访问了成员变量,对A对象空间进行了访问,会报错;Show函数没有对this指针解引用,只是打印了一些信息,所以不会造成错误。
当然,这里补充一点,一个类对象只存储其成员变量,而不存储成员函数,否则对于一个类实例N次,会需要存储N次同样的成员函数,这显然是不合理的设计,因此,成员函数被统一存储在公共代码段,那么调用成员函数,并不会访问p指向的空间,
class A
{
public:
void PrintA(A* this)
{
cout<<(*this)._a<<endl;
}
void Show(A *this)
{
cout<<"Show()"<<endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->PrintA(p);
p->Show(p);
}