类和对象(上篇)之面试题(结构体内存对齐)
c++中struct和class的区别是什么
问题:C++中struct和class的区别是什么?
解答:C++需要兼容C语言,所以C++中struct可以当成结构体去使用。另外C++中struct还可以用来定义类。 和class是定义类是一样的,区别是struct的成员默认访问方式是public,class是struct的成员默认访问方式是private。
【面试题】 面向对象的三大特性:封装、继承、多态。
问题:我们通过对下面的不同对象分别获取大小来进行分析
#include<iostream>
using namespace std;
//类中既有成员变量,又有成员函数
class A1
{
public:
void f1()
{}
private:
int _a;
};
//类中仅有成员函数
class A2
{
public:
void f2()
{}
};
//类中什么都没有——空类
class A3
{
};
sizeof(A1):?
sizeof(A2):?
sizeof(A3):?
结论:一个类的大小,实际上就是该类中“成员变量”之和,当然也要进行内存对齐,注意空类的大小,空类比较特殊,编译器给了空类一个字节来标识这个类。
结构体内存对齐
1.第一个成员在与结构体偏移量为0的地址处。
2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
注意:对齐数=编译器默认的一个对齐数与该成员的较小值。
vs默认对齐数为8,gcc默认对齐数为4.
3.结构体总大小为:最大对齐数的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是 所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
面试题
- 结构体怎么对齐? 为什么要进行内存对齐
- 如何让结构体按照指定的对齐参数进行对齐
- 如何知道结构体中某个成员相对于结构体起始位置的偏移量
- 什么是大小端?如何测试某台机器是大端还是小端,有没有遇到过要考虑大小端的场景
举例说明:
//例子1
struct s1
{
char c1;
int i;
short s2;
};
printf("%d\n", sizeof(struct s1));//12
//例子2
struct s2
{
char c1;
short s2;
int i;
};
printf("%d\n", sizeof(struct s2));//8
案例一分析
char类型占一个字节,编译器默认对齐数是8,所以该变量的对齐数为1,实际偏移量为0;
int类型占了4个字节,所以该变量的对齐数为8,实际偏移量是4
short类型占了2个字节,所以该变量的对齐数为2,实际偏移量为8
判断机器的大小端
int check_sys()
{
int a = 1;
return *(char*)&a;
}
int main()
{
int ret = check_sys();
if (ret == 1)
printf("daduan");
else
printf("xiaoduan");
}
int check_sys()
{
union
{
int i;
char c;
}un;
un.i = 1;
return un.c;
}
this指针的特性
1.this指针的类型:类型*const
2.只能在“成员函数”的内部使用
3.this指针本质其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
4. this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递
面试题
1.this指针存在哪里?
解答:其实编译器在生成程序时加入了获取对象首地址的相关代码。并把获取的首地址存放在了寄存器ECX中(VC++编译器是放在ECX中,其它编译器有可能不同)。也就是成员函数的其它参数正常都是存放在栈中。而this指针参数则是存放在寄存器中。类的静态成员函数因为没有this指针这个参数,所以类的静态成员函数也就无法调用类的非静态成员变量。
2.this指针可以为空吗?
可以为空,当我们在调用函数的时候,如果函数内部并不需要使用到this,也就是不需要通过this指向当前对象并对其进行操作时才可以为空(当我们在其中什么都不放或者在里面随便打印一个字符串),如果调用的函数需要指向当前对象,并进行操作,则会发生错误(空指针引用)就跟C中一样不能进行空指针的引用