面试杭州某互联网大厂的时候被问了一些C++11的问题,发现还有一些不熟悉的名词和特性,在这边就补充一下。
std::atomic
算是通过面试发现了一个宝藏吧,可以不用锁来实现线程互斥。通过面试是一个模板类,可以将自定义类,或者基本数据类型作为T来特化atomic类来实现原子类型。
在load和store类对象的时候,有一个memory_order参数。这里贴上六个参数分别表示的含义。具体细节可以去cppreference上看,还涉及到了x86架构和arm架构。
memory_order | 作用 |
---|---|
memory_order_relaxed | 只保证当前操作的原子性,不管其他线程的读写顺序 |
memory_order_comsume | 确保本线程依赖该变量的读写不会被重新排到当前load之前 |
memory_order_acquire | 向前保证,确保所有本线程的读写操作不会被重新排到当前load之前。也就是load后面的语句均未执行。 |
memory_order_release | 向后保证,确保所有本线程的读写不会被重排到store后面,也就是说store之前的语句都已经被执行了。 |
memory_order_acq_rel | 同时包含acquire和release |
memory_order_seq_cst | 顺序一致性,也就是说执行顺序不会被打乱,会确保每个处理器执行代码的时候与源代码顺序一致,同时多个处理器看到的不同线程交错执行顺序是固定的。 |
RTTI
这个RTTI好像是被问到了,当时我没太反应过来,上来一串英语,终究是不够熟悉。
结束后我打开C++ Primer Plus,一看目录,诶,正好在520页。翻到520页,熟悉的dynamic_cast 映入眼帘,好家伙原来是这个玩意,当时应该多问问的。
既然翻到了这里,那也再次学习一下那些已经知道和不知道的知识吧。
RTTI 是运行阶段类型识别(Runtime Type Identification)的简称。 加入C++11的目的主要是为了能够统一标准,让类库不用自己设计一些实现来做到这件事。(PS:既然书上说了类库能够自己实现这个,那么怎么实现这个呢?我想了一下,应该还是通过虚函数,最简单的就是设计一个虚函数,函数返回一个字符串或者整数,用字符串或者整数来标定一个特定的类,比如返回0 表示父类,返回1表示子类1,返回2表示子类2…)
C++有3个支持RTTI的元素,dynamic_cast、typeid以及type_info。RTTI应该只用于包含虚函数的类层次结构。 因为若没有虚函数,那么析构函数也不是虚函数,那么将子类的对象交给基类指针后,delete基类指针,调用的也是基类的析构函数,子类的一些内容就会产生内存泄露,所以在没有虚函数的情况下,将子类对象交给基类指针来管理是一件不应该出现的事情。
dynamic_cast,可以尝试将一个对象的指针转换成一个特定类型的指针,如果不能转换就返回nullptr。(只能将指针转成对象类型的指针和对象类的基类指针。) 当然也可以用于转换引用,但是因为没有空引用的定义,所以不能转换时就会抛出bad_cast异常。
typeid运算符和type_info类。调用typeid可以直接返回一个对象的type_info,type_info有个成员函数name(),返回一个包含类型信息的字符串,通常是类名(当然具体要看厂商实现),typeid运算符能确定两个对象是否为同种类型。