c++11特性
转义字符1. \n换行(把字符转换为有特殊含义的字符)\t制表符2.把特殊含义的字符转换为普通字符 windows中\表示路径 转义为一个反斜杠linux系统中路径使用 /来表示 eg:/rootR"xxx()xxx" xxx要相等,作用等于注释原始字面量R可以直接表示字符串的实际含义,不会做链接转义等操作。
1.原始字符串的字面量
转义字符1. \n换行(把字符转换为有特殊含义的字符)\t制表符
2.把特殊含义的字符转换为普通字符 windows中\表示路径 转义为一个反斜杠
linux系统中路径使用 /来表示 eg:/root
R"xxx()xxx" xxx要相等,作用等于注释
原始字面量R可以直接表示字符串的实际含义,不会做链接转义等操作。
2.constexpr
constexpr是一种比const 更严格的束缚, 它修饰的表达式本身在编译期间可知,C++11之前编译器没办法区分表达式是否为常量表达式。
常量表达式要在程序编译时执行,普通变量要在程序运行时执行
const int a1 = 10; // a1是常量表达式。
const int a2 = a1 + 20; // a2是常量表达式
int a3 = 5; // a3不是常量表达式
const int a4 = a3; // a4不是常量表达式,因为a3程序的执行到达其所在的声明处时才初始化,所以变量a4的值程序运行时才知道。但编译没问题!
以上代码可正常编译。
说明了const声明的不一定就是常量表达式!
因为a3不是常量表达式,a4是常量表达式,但是a3需要在a4前执行而且是运行时,因此a4不能在编译时执行,故说明const并不一定是常量表达式
const:函数中的形参-变量只读,修饰常量
constexpr int i=0;//在编译阶段就可以识别为常量表达式,提高程序效率
const int i=0;
c++基础数据类型可以使用,自定义数据类型(struct/class)不可以使用constexptr
定义结构体或者类时不可以使用。
constexptr struct{}//错误
constexptr struct t;//可以 常量表达式
3.final 写在类/函数名后面
final限制类表示类不能被继承;修饰函数只能是虚函数,虚函数不能被重写
void son() final{};在子类的虚函数中写表示子类不会再有子子类
class chlid final:public base{};基类不会再有派生类。–丁克
override
条件:1.有继承关系2.子类重写父类虚函数3.父类指针指向子类对象
加了关键字后,提高程序的可读性,保证重写的虚函数是正确的
override 就是辅助你检查是否继承了想要虚继承的函数。:假设在重写中写错了,比如做不到同名,同参,同返中的任意一样,编译器都会给出提示。
- 编译时多态性:通过重载函数实现
- 运行时多态性:通过虚函数实现。
重载:在一个类中函数名相同,参数不同 eg:构造方法的重载
重写:不同类中,函数名形同,参数相同 eg:子类对父类,
纯虚函数声明如下: virtual void funtion1()=0; 纯虚函数一定没有定义,纯虚函数用来规范派生类的行为,即接口。包含纯虚函数的类是抽象类,抽象类不能够实例化,但可以声明指向实现该抽象类的具体类的指针或引用。
抽象类不能实例化出对象,子类即使在继承后也不能实例化出对象:
只有重写纯虚函数,子类才能实例化出对象:
定义指针时如果 new 父类对象因为是纯虚函数,自然是 new 不出来的,但是可以 new 子类对象:
4.统一的初始化列表
//c++11之前数组和结构体有相同的初始化方式,后面加{}
int arr[] = {1,2,3,4};
double arr[] = {1,2,3,4};
struct{
int id;
double age;
}zhangsan{1,28}
变量数组,对象统一了数据的初始化方式
5.initilizer_list 轻量级的类模板
可以进行任意长度的数据初始化,但必须是同种类型
三个接口、size、begin、end
6.基于范围的for循环
更加精简高效 只需要指定范围,不需要边界
for(declaration:expression)
两个表达式声明和遍历的对象
范围for循环的写要加引用&
for(auto &e : Qlist)
7.右值引用 && ???
从4行代码看右值引用 - qicosmos(江南) - 博客园 (cnblogs.com)
左值:存储在内存中,有明确的内存地址
右值:可以提供数据值,数值不能取地址
右值引用,生命周期与右值引用类型变量的声明周期相同,
临时对象的构造、拷贝、销毁会占用系统资源,引用临时对象的值,省去构造、拷贝、析构的过程,可以提高系统效率
引用作参数可以省去拷贝和构造的过程,提高效率,但如果是函数需要返回局部变量,就需要值传递,值传递就会进行拷贝,可以用右值引用
如果没有右值引用,用对象接收,会调用拷贝构造,对于string/vector等容器,需要进行深拷贝。效率低。
右值引用:
右值引用的主要应用就是重载了移动构造函数,利用了将亡值,将将亡值的空间内容交换到要拷贝的对象中。减少了深拷贝。
move资源的转移
move方法可以将左值转换为右值,并不移动任何东西而是和移动构造函数一样,将对象的状态或者所有权从一个对象转移到另一个对象,只有转移没有拷贝
8.auto
堆、栈、全局区:(局部static变量,全局static变量)、全局变量和常量。
常量区:这是一块比较特殊的存储区,他们里面存放的是常量字符串,不允许修改
代码区:存放程序的二进制代码
c中auto修饰局部变量,不管加不加都是anto int a;自动局部变量:在栈区自动分配空间自动维护
c++11:自动推导类型
auto的自动类型推导用于从初始化表达式中推断出变量的数据类型。通过auto的自动类型推导,可以大大简化我们的编程工作
1.auto定义变量时必须初始化;auto a;a=10;错误
2.auto不可以作为函数形参,qt可以;
3.auto变量不可以作为自定义类型的成员变量eg结构体
4.不能定义auto数组
5.模板实例化类型不能是auto
9.nullptr
在 C++中,NULL 被定义为整形常量 0(而在 C 中,NULL被定义为无类型指针常量 (void*) 0 )。
nullptr是为了解决原来C++中NULL的二义性问题而引进的一种新的类型,
引入了nullptr是void*类型的,只能给指针赋值。
10.lambda表达式
它可以用于创建并定义匿名的函数对象,不需要额外的命名函数和对象,,比较灵活和简洁。
Lambda的语法如下:[捕获列表](函数参数)mutable或exception声明->返回值类型{函数体}
lambda表达式的底层原理就是类的可调用对象,operate运算符的重载
捕获列表:
[]表示一个空的捕获列表,也就是说,这个 lambda 表达式不会捕获任何外部变量,也不能访问任何外部变量。
[&] 表示一个引用捕获列表,也就是说,这个 lambda 表达式会以引用的方式捕获所有外部变量,并且可以访问和修改它们。
[=] 按值捕获。捕获外部作用域中所有变量。
| [names] | names是一个逗号分隔的名字列表,这些名字都是Lambda所在函数的局部变量。默认情况下,这些变量会被拷贝,然后按值传递,名字前面如果使用了&,则按引用传递 |
mutable 一般只用于成员变量和lambda表达式,在代码中表示 可变数据成员
在lambda捕捉列表 [ = ] 采用 传值方式捕捉外部变量 时,编译器将该表达式翻译成一个未命名类的未命名对象。该类含有一个经过const 修饰放入重载调用运算符。
而加入 mutable后,相当于把 operator 的 const 修饰去掉,这样就可在函数内部对 传值方式捕捉的变量进行修改。
11.智能指针
智能指针是对裸指针的一种封装,初衷让程序员无需手动释放内存,避免内存泄漏。
智能指针是存储对象指针的类,确保指针离开作用域时,会自动销毁动态分配的对象,防止内存泄漏
智能指针的核心实现技术内部维护了一个计数器,引用计数,每使用它一次,内部引用计数加1,每析构一次内部的引用计数减1,减为0时,删除所指向的堆内存。
C++11中提供了三种智能指针,使用这些智能指针时需要引用头文件<memory>:
shared_ptr:共享的智能指针
unique_ptr:独占的智能指针
weak_ptr:弱引用的智能指针,它不共享指针,不能操作资源,是用来监视shared_ptr的。
1.shared_ptr
当一个资源需要多个对象共享时,存在循环应用问题,结合weak_ptr使用。
多个指针共同管理一块内存,使用一次内部引用计数加1,析构一次引用计数减1,减为0删除指向的堆内存。
引用计数加:
a新建了一个shared_ptr并指向一个资源
b复制构造函数创建了一个新的shared_ptr
c用复制运算符将一个shared_ptr给另外一个shared_ptr赋值时
减:对象被销毁,类变量被析构;通过reset方法或者赋值运算符给另外一个资源时
2.unique_ptr
通过在析构函数释放资源来管理对象的生命周期,来自动管理资源, 内存只能通过唯一的指针来管理
最大的特点就是对资源的独占,不可以复制。相比share_ptr更加高效,避免循环引用问题
move进行资源的管理,引用计数永远为1
3.weak_ptr
不具备内存管理能力,主要是解决share_ptr可能导致的循环引用问题,原理就是指向某个资源时,不增加引用计数。
1.循环引用 a存储b,b存储a,共同管理的内存引用计数永远不能减为0,用弱引用指针
#include<memory>
class MyClass{
pulic:
shared_ptr<MyClass> other;// 存在循环引用问题
weak_ptr<MyClass> other;// 引用计数不会增加
MyClass(){}
~MyClass(){}
}
int main(){
shared_ptr<MyClass> ptr1(new MyClass());
shared_ptr<MyClass> ptr2(new MyClass());
ptr1->other = ptr2;//共享ptr2的引用计数为2
ptr2->other = ptr1;//共享ptr1的引用计数为2
return 0; //离开作用域,调用析构函数 引用计数-1
}
子对象发送父对象信号:强制类型转换
qobject_cast<MainWindow *>(parent)->sig();
更多推荐
所有评论(0)