某日二师兄参加XXX科技公司的C++工程师开发岗位第10面:
面试官:了解
sizeof
操作符吗?二师兄:略微了解(不就是求大小的嘛。。)
面试官:请讲以下如何使用
sizeof
?二师兄:
sizeof
主要是求变量或者类型的大小。直接使用sizeof(type)
或sizeof(var)
即可。面试官:嗯。
sizeof(int*)
、sizeof(int**)
和sizeof(int[4])
各返回什么?二师兄:前两者的返回值相等。在32位操作系统中返回4,64位操作系统中返回8。
sizeof(int[4])
返回16,是因为sizeof
运算时数组不会退化为指针。面试官:如果一个
int* p = nullptr
,那么对其进行sizeof(*p)
会发生什么?二师兄:返回4。原因是
sizeof
在编译时求值,sizeof
只需要获取*p
的类型,并不对*p
求值。所以不会发生段错误。面试官:下面三个
szieof
运算符,各返回什么?
#include
#include
int main(int argc, char const *argv[])
{
const char* str1 = "hello";
char str2[] = "hello";
std::string str3 = "hello";
std::cout << sizeof(str1) << std::endl;
std::cout << sizeof(str2) << std::endl;
std::cout << sizeof(str3) << std::endl;
}
二师兄:第一个返回4或8,因为它是个指针,第二个是个数组,不过末尾有个
\0
结束符,所以它的值是6,第三个不清楚,但是等于sizeof(std::string)
。面试官:好的。使用
sizeof
对以下两个结构体求大小,
#include
struct Foo
{
char c;
int i;
double d;
};
struct Goo
{
char c;
double d;
int i;
};
int main(int argc, char const *argv[])
{
std::cout << sizeof(Foo) << std::endl;
std::cout << sizeof(Goo) << std::endl;
}
二师兄:
sizeof(Foo)
应该等于16,而sizeof(Goo)
应该等于24。因为需要内存对齐。面试官:好的。那你知内存对齐的原则是什么,为什么要内存对齐?
二师兄:额。。。应该需要以8位对齐吧。。。不是很清楚为什么要内存对齐。
面试官:你知道
sizeof(空结构体)
的结果是多少吗?二师兄:应该是0吧。
面试官:对只有一个函数的类进行
sizeof
运算结果是多少?二师兄:应该也是0?
面试官:好的,回去等通知吧。
让我们复盘以下今日二师兄的表现。
内存对齐的原则是什么,为什么要内存对齐?
主要有以下原则:
- 结构体变量的首地址是其最宽基本成员类型大小的整数倍。
- 结构体每个成员相对于结构体首地址的偏移量都是成员大小的整数倍。
- 结构体的总大小为结构体最宽基本成员类型大小的整数倍。
因为性能。为了缓存友好(Cache friendly)。这是一个很大的话题,咱们今天聊不了太多。
sizeof(空结构体)
的结果是多少?
这里在C中是0,在C++中是1。C++标准规定,不同的对象不能拥有相同的内存地址。 如果空类大小为0,类的对象数组中的每个对象都拥有了相同的地址,这显然是违背标准的。
对只有一个函数的类进行
sizeof
运算结果是多少?
这里也是一个坑。要看这个函数是不是虚函数。如果不是虚函数,则结果是1,如果是虚函数,则大小是4或者8。
聪明的小伙伴,提到4或者8.就应该知道是怎么回事了吧?
好了,今日份面试到这里就结束了,小伙伴们,对于今天二师兄的面试,能打几分呢?如果是你,以上的问题都能回答的上来吗?
关注我,带你21天“精通”C++!(狗头)