[Blog] [Docs] [Code] [Slides] [About]

C++语言标准面试题精选

2020-05-06 18:00 CST

2020-05-06 19:02 CST

代码不标准,找bug两行泪。要想代码写得好,就要精通C++(和C++标准)。下面精选了一些无理取闹深入标准的造火箭面试题,供自己参考。

空结构体

  • 在C语言中,空结构体的大小是0字节,因为什么都没有。
  • 在C++中,每个对象都要有唯一的内存地址,空结构体的大小是1字节。

额外考点:STL模板库+内存填充

struct dummy {};
std::pair<int, dummy> p;
std::tuple<int, dummy> t;
  • pair在实现中往往是一个sturct,由此其内存大小为8(4+1+3)。
  • tuple在实例化模板时空结构体被编译器优化了,其内存大小为4。

参考资料:http://aequa.me/index.php/2019/08/01/why-stdpair-and-stdtuple-differ-in-size/

Lambda表达式

Lambda表达式在实现上实现了一个闭包类型,可以看作是一个重载了函数调用运算符operator()的结构体。

  • 按复制捕获的对象会在闭包中变为匿名非静态成员,按照对象大小分配内存单元;
  • 按引用捕获的对象行为未定义,clang的实现大概是在闭包中放了个指针。

额外考点:隐式类型转换+内存填充

char a, b;
int c;
auto f1 = [=]() { a + b + c; };
auto f2 = [&]() { a + b + c; };
auto f3 = [=]() {};
void *(f4)() = [=]() {};
  • f1是一个Lambda表达式,通过复制捕获了三个对象,其大小为8(内存填充)。
  • f2是一个Lambda表达式,通过引用捕获了三个对象,在64位机clang编译下其大小为24。
  • f3是一个Lambda表达式,没有捕获对象,其大小为1(空)。
  • f4是一个隐式转换得到的函数指针,64位机下其大小为8。

静态变量

以如下代码为例:

void foo() {
  static i = 0;
  cout << ++i << endl;
}

i是函数的静态变量,会在编译时被初始化并存储在.bss区,全局只有这一份数据。

额外考点:模板实例化

#include <iostream>

template <class T>
void foo(T) {
  static i;
  std::cout << ++i << std::endl;
}

int main() {
  int a;
  double b;
  const int c;
  foo(a), foo(b), foo(c);
}
  • const int类型推导为int
  • 总共实例化了两个模板,输出为1、1、2。

重载决议

通过名称查找函数找到多个实例/模板时,需要进行重载决议。重载决议的细节很多,最重要的第一条比较规则就是隐式转换排行。

隐式转换共有三种级别,取最低等级:

  • 准确匹配:不要求转换、左值到右值转换、限定性转换、函数指针转换、类类型到相同类的用户定义转换;
  • 提升:整型提升、浮点提升;
  • 转换:整型转换、浮点转换、浮点整型转换、指针转换、成员指针转换、布尔转换、派生类到其基类的用户定义转换。

类型提升(窄到宽)能够保留原有数据,是第二等级;而类型缩窄(宽到窄)属于整型/浮点转换,会丢失部分数据,属于最差的第三等级。

限定性转换也是有排行的,如果S1转换结果可以通过限定性转换转换为S2的结果,则S1更优。派生类到基类转换也是有排行的,如果如果S1转换结果可以通过上行/下行(同方向)转换为S2的结果,则S1更优。(简单的说就是转换越少越优)。

#include <iostream>
void foo(const int*, short) {
  std::cout << "const int*, short" << std::endl;
};
void foo(int*, int) {
  std::cout << "int*, int" << std::endl;
};

int main() {
  int i = 0;
  short s = 0;
  foo(&i, s);
}

以上程序编译运行的结果是?

答案:按C++标准,以上程序无法编译。

原因:int* -> const int*的隐式转换比不转换差,short -> int的转换比不转换差,从可行重载函数集合中无法得到最优者。

参考资料:https://zh.cppreference.com/w/cpp/language/overload_resolution

好了,以上都学会(面向C++标准编程),你造的火箭就能送用这些题考核别人的人上天啦。

<EOF>

Loading Comments By Disqus