C++11常用知识点总结

智能指针

在整理智能指针之前先说一个名词:悬挂指针,悬挂指针也叫野指针,产生的原因有两种:定义指针的时候没有初始化;delete或free之后没有将指针置空;需要注意的一点是,free和delete只是将指针指向的内存释放了,但是并没有将指针所指向的地址进行置空,当执行完delete或free后,指针指向的位置已经被资源回收但是仍然指向这块地址,需要手动设置为null,防止野指针的调用。

auto_ptr

保证同一时间只有一个只能指针指向该对象,独享对象的所有权,将一个对象的所有权转让给另一个对象后,原来的对象就会成为悬挂指针,已经不能再用了,存在潜在的内存崩溃,C++11已经弃用该函数

unique_ptr

特性接近auto_ptr,保证同一时间只有一个智能指针指向该对象,独享对象的所有权,不允许将一个智能指针赋值给另一个智能指针,只能通过move函数将所有权转让给另一个智能指针,以警醒的方式告诉使用者,已经将所有权转移给了下一个对象,就不要使用原来的指针了,但是可以使用右值智能指针赋值给另一个智能指针,因为这种方式不会产生悬挂指针。例如:unique_ptr a = unique(new 3);

share_ptr

底层采用引用计数的方式实现资源可以被多个指针共享对象,解决了unique_ptr独占对象所有权的问题,可以通过get函数获取原来的指针。
循环引用的场景:A类中有B类的shate_ptr指针b,B类中有A类的share_ptr指针a,分别定义A和B类的对象a、b(此时a和b的引用计数都是1),a.b=b,b.a=a(此时a和b的一引用计数都+1变为2),此时销毁对象a和b,应用计数都减一,最后a和b的引用计数都为1,永远都不会降低为0,对象永远无法被销毁,造成内存泄漏。

share_ptr的缺点

  • 当发生循环引用的时候,会导致内存的泄漏。
  • 除了保证指针之外还需要维护引用计数,比普通指针的开销要大,处理时间也更长
  • 指向的对象必须通过new的方式产生,时间消耗比较多
  • 引用计数的操作必须是原子性的,比较耗时
  • 若在类中share_ptr成员变量被赋值为this(这属于自己给自己挖坑),在销毁该类的对象时,先释放share_ptr对象,调用一次类的析构函数,对象销毁时又调用一次类的析构函数,对象两次释放被double free

weak_ptr

该指针是为了辅助share_ptr而生的智能指针,只可以从share_ptr或weak_ptr那里构造对象,不会引起指向资源的引用计数的增加,从而解决sahre_ptr中循环引用的死锁问题,将循环引用中的任何一个类对象中的share_ptr修改未weak_ptr即可。weak_ptr通过lock函数获取share_ptr。

lambda表达式

[捕获值的方式] (参数列表) ->返回值类型 throw(抛出异常的参数列表){函数体}
lambda的最下单元{}
捕获值的方式有两种:值捕获和引用捕获

[] :空捕获列表,lambda不使用所在函数中的变量。一个lambda只有捕获变量后才能使用它们
[names]:隐式捕获列表,names是一个逗号分割的名字列表,这些名字是lambda表达式所在函数的句柄变量。默认情况下,捕获列表中的变量被拷贝,名字前如果有&则采用引用捕获的方式。
[&]:引用捕获lambda函数所在函数中的所有变量
[=]:值捕获lambda表达式所在函数的所有变量
[&,names]:names是一个逗号分隔的列表,这些列表采用值捕获的方式,任何隐式捕获的变量都采用引用方式捕获,names的前面不能使用&
[=,names]:names是一个逗号分隔的列表,任何隐式捕获的变量都采用值捕获的方式,names中的名字不能包含this,且这些名字前必须使用&

  • lambda的返回值类型只能采用尾置类型的方式
  • lambda的参数列表不允许有默认值
  • 捕获列表只用于局部非static变量,lambda中可以直接使用局部static变量和它所在函数之外声明的变量。

using = 代替typedef为类型定义别名

using INT = int
using = 可以在类型重定义时其中带有类型参数,而typedef不行
typedef QMap<T,int> MAPI //非法
using AAA = QMap<T,int> 没问题

新增数据类型

long long,unsigned long long(用来支持64bit宽度) char16_t,char32_t用来支持16位和32位字符

{}扩大了使用范围

原来的{}用于定义作用域

class A{
A(int a,int b){}
};
  • 对象类型可以自动调用其构造函数 ,用法一:A a{10,20}; 用法二:A a = {10,20};
  • 可以防止向下转型 例如:char a = 1.234//会向下转型为double类型,而这种转化是非法的,char可以向int转化;而 char a = {1.234}会编译报错,拒绝向double转化。

有向下转型也有向上转型,意思就是类型的转化,数值类型就比如,char类型,int类型,double类型等,声明一个该类型的对象,占用的空间越累越大,能存放char的数据一定可以放在int的空间中去存储,而不会造成溢出,同理,存储的int数据也完全可以存放在double中,而不会造成溢出。从char到int到double就属于向下转型,相反就是向上转型。所以我们一般认为向下转型是安全的,而向上转型就不一定了。包括父子类之间,也会存在向下转型和向上转型的情况。

一个空类默认的函数

无参构造、拷贝构造,拷贝赋值函数、析构函数、移动构造和移动赋值运算符。

C++11新引入的几个常用关键词

  • nullptr 表示空指针,C++用0来表示空指针,0即表示空指针又表示整数,为了解决0类型混乱的问题,引进了nullptr来专门表示空指针,为了与原来的语法兼容,nullptr==0返回值为true
  • auto 自动类型推断 例如:int a = 10; auto b = a; //b会被推断为int类型
  • decltype 类型说明符, 使用举例 :int a = 10; decltype(a) b;// b会直接沿用a的类型
  • explicit 用在函数声明之前,防止隐式类型转换,主要针对类型转换的函数
  • default 类中有默认的6个函数,当重载某个函数时,默认提供的对应函数就不会再提供,如果在重定义以上6个函数时仍想使用提供的默认函数使用default关键字 class A{ A() = default;};有一点需要注意,default关键字只能用在默认的6个函数中
  • delete 禁止编译器编译,使用方式与deault一致,可以使用在类中的任何函数中
  • override 用在子类中,明确告诉编译器,该函数是为了覆盖(重写)父类中的同名函数,如果在子类中被override修饰的函数不能与父类中的函数实现覆盖,则会编译报错
  • final 用在父类中,表示该函数不能被子类覆盖
  • noexcept 表示函数不抛出异常 ,使用举例 void func() noexcept;
  • class/struct关键词在同一作用域中定义同名枚举,使用方式如下:
enum Old{yes,no}
enum OO{yes,no}//在同一作用域中第二行会报错,因为yes和no已经存在
enum class AA{yes,no} //此种写法不会与第一行冲突,使用时注意使用AA::yes

右值引用&&

右值引用的本质是为了防止没必要的复制操作。
相对于左值,右值就是字面常量、表达式、函数的非引用返回值等

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值