新特性你都了解多少?
1.类型推导:auto,decltype
auto:auto x = 10; 自动推导x为int型变量。
decltype:C++11的类型推导详解 - 知乎 (zhihu.com)
2.智能指针
3.初始化列表
4.nullptr:之前的NULL存在二义性,实际上是0
5.多线程:C++并发编程(C++11到C++17)-阿里云开发者社区 (aliyun.com)
6.std::bind绑定器
7.std::function
8.lambda表达式
谈一谈你对左值和右值的了解,了解左值引用和右值引用吗?
1.可被赋值的变量称为左值,只能作为数据赋值的为右值。
2.有名称,可以获取到存储地址的为左值,不能通过取地址符获取的称为右值。
凡是真正的存在内存当中,而不是寄存器当中的值就是左值,其余的都是右值。也就是取地址(&
)操作可以成功的是左值,其余都是右值。
【C++】左值和右值、左值引用(&)和右值引用(&&)_Jacky_Feng的博客-CSDN博客
了解移动语义和完美转发吗? 移动语义(move semantic)和完美转发(perfect forward)_donnyxia1128的博客-CSDN博客_移动语义
主要应用场景是在移动构造函数中。
在类似工厂模式等设计中,需要调用两次拷贝构造函数,这样开销比较大,通过移动构造函数实际做了一次浅拷贝,并把之前的指针置空。
移动语义:std::move()
完美转发:std::forward<T>(t)
了解列表初始化吗?
1.默认参数类型如 int、float等类型,使用初始化列表或者在构造函数中初始化影响不大。
2.自定义的类类型,应该使用初始化列表进行初始化,这样会减少一次调用默认构造函数的过程,对于数据密集型的会很大提高效率。
平时会用到function、bind、lambda吗,都什么场景下会用到?
function:最大作用在于实现回调
bind:
lambda:就地封装短小的功能闭包,可以及其方便地表达出我们希望执行的具体操作,常用于回调函数。
对C++11的mutex和RAII lock有过了解吗?
mutex:互斥量,多线程时有用,避免多个线程同时对一个数据进行操作。
std::lock_guard(RALL机制的锁,在构造函数加锁,在析构函数中释放锁。可以加大括号控制锁的作用域,超出锁的作用域时会自动析构解锁)
对C++11的智能指针了解多少,可以自己实现一个智能指针吗?
shared_ptr:
首先智能指针的出现是为了减少因为忘记手动释放内存空间而导致的内存泄露。
主要原理是通过RALL机制完成。
1.首先写一个类
2.在类的构造函数中传入指针类型,创建一个指针(计数加一)。
3.设置一个计数器,保存这个指针被拷贝、赋值了多少次,需要重写拷贝构造函数中(计数加一)、赋值构造函数(对方加一,自己减一,如果目标为0了需要调析构函数)
4.析构函数中释放指针的内存空间(计数为0时释放,不为0时减一)。
weak_ptr:
相对于shared_ptr来说,weak_ptr只有内存的访问权而没有指向内存的所有权,并不能直接释放掉所指向的内存。
weak_ptr只能用shared_ptr来进行初始化。
unique_ptr:
保证对持有对象的唯一访问权
1.unique_ptr
不能被复制到另外一个unique_ptr
2.unique_ptr
所持有的对象只能通过转移语义将所有权转移到另外一个unique_ptr
unique_ptr如何转换所有权?
std::unique_ptr<A> a1(new A());
std::unique_ptr<A> a2 = a1;//这样编译会报错,不允许这样复制
std::unique_ptr<A> a3 = std::move(a1);//可以转移所有权,所有权转义后a1不再拥有任何指针
enum 和 enum class有什么区别?
一般什么情况下会出现内存泄漏?
1.new 或者malloc申请了内存空间后,使用完毕后忘记释放内存空间
2.new[]与delete[]未配套使用
3.当基类指针指向子类对象时,如果基类的析构函数不是virtual,那么子类的析构函数将不会被调用,子类的资源没有正确是释放,因此造成内存泄露
4.指针被重新赋值,而之前的内存未释放
怎么用C++在编码层面尽量避免内存泄漏?
1.使用new malloc后应该记得delete或free
2.new[]与delete[]应尽量配套使用
3.每次指针在被重新赋值前应该确认之前的空间是否已经释放
谈一谈你对面向对象的理解什么场景下使用继承方式,什么场景下使用组合?