- default和delete
default:在C++中,声明自定义的类型之后,编译器会默认生成一些成员函数,这些函数被称为默认函数,我们使用default可以显示的让编译器去生成该函数的默认版本
delete:弃置函数,函数后添加“=delete”之后,此函数将不允许被调用
示例:
class Test
{
public:
Test() = default;//默认构造函数
Test& operator=(const Test&) = delete;
Test(const Test&) = delete;
}
int main()
{
Test test1;
Test test2 = test1;// 错误,拷贝构造函数被禁用
Test test3;
test3 = test1;// 错误,拷贝赋值操作符被禁用
return 0;
}
- auto和decltype
auto:通过=右边的类型推导出变量的类型
auto n = 100;//n 的类型为int
decltype :推导表达式类型,编译器只是分析表达式并得到它的类型,却不进行实际的计算表达式的值
decltype(f()) n = 10;//n的类型为f()函数返回值类型
- final 和override
final:指定某个虚函数不能在子类中被覆盖,或者某个类不能被子类继承
class Base
{
public:
virtual void foo();
};
class Test1: Base
{
public:
void foo() final; // Base::foo 被覆盖而 A::foo 是最终覆盖函数
void bar() final; // 错误: bar 不能为 final 因为它非虚
};
class Test2 final : Test1// class Test2 为 final
{
public:
void foo() override; // 错误:foo 不能被覆盖,因为它在 Test1 中是 final
};
class Test3 : Test2 // 错误:Test2 为 final
{
};
override:该函数为虚函数并覆盖某个基类中的虚函数
class Base
{
public:
virtual void foo();
void bar();
};
class Test : Base
{
public:
void foo() const override; // 错误:B::foo 不覆盖 Base::foo
void foo() override; // OK:Test ::foo 覆盖 Base::foo
void bar() override; // 错误:Base::bar 非虚
};
- 右值引用
提到右值引用,先看一下下面几个概念:
左值:可以取地址并且有名字的东西就是左值。
右值:不能取地址的没有名字的东西就是右值。
纯右值:运算表达式产生的临时变量、不和对象关联的原始字面量、非引用返回的临时变量、lambda表达式等都是纯右值。
将亡值:可以理解为即将要销毁的值。
左值引用:对左值进行引用的类型。
右值引用:对右值进行引用的类型。
移动语义:转移资源所有权,类似于转让或者资源窃取的意思,对于那块资源,转为自己所拥有,别人不再拥有也不会再使用。
完美转发:可以写一个接受任意实参的函数模板,并转发到其它函数,目标函数会收到与转发函数完全相同的实参。
返回值优化:当函数需要返回一个对象实例时候,就会创建一个临时对象并通过复制构造函数将目标对象复制到临时对象,这里有复制构造函数和析构函数会被多余的调用到,有代价,而通过返回值优化,C++标准允许省略调用这些复制构造函数。 - 列表初始化
int n{123}; // c++11
- std::function & std::bind & lambda表达式
std::function:可以理解为一个函数对象,可以用于回调函数
std::bind:可以将调用对象和参数一起绑定,绑定后的结果使用std::function进行保存,并延迟调用到任何我们需要的时候
void fn(int n1, int n2, int n3) {
std::cout << n1 << " " << n2 << " " << n3 << std::endl;
}
int fn2() {
std::cout << "fn2 has called.\n";
return -1;
}
int main()
{
using namespace std::placeholders;
auto bind_test1 = std::bind(fn, 1, 2, 3);
auto bind_test2 = std::bind(fn, _1, _2, _3);
auto bind_test3 = std::bind(fn, 0, _1, _2);
auto bind_test4 = std::bind(fn, _2, 0, _1);
bind_test1();//输出1 2 3
bind_test2(3, 8, 24);//输出3 8 24
bind_test2(1, 2, 3, 4, 5);//输出1 2 3,4和5会被丢弃
bind_test3(10, 24);//输出0 10 24
bind_test3(10, fn2());//输出0 10 -1
bind_test3(10, 24, fn2());//输出0 10 24,fn2会被调用,但其返回值会被丢弃
bind_test4(10, 24);//输出24 0 10
return 0;
}
lambda:匿名函数,语法形式 auto func = [capture] (params) opt -> ret { func_body; };
lambda表达式允许捕获一定范围内的变量:
[]不捕获任何变量
[&]引用捕获,捕获外部作用域所有变量,在函数体内当作引用使用
[=]值捕获,捕获外部作用域所有变量,在函数内内有个副本使用
[=, &a]值捕获外部作用域所有变量,按引用捕获a变量
[a]只值捕获a变量,不捕获其它变量
[this]捕获当前类中的this指针
- 模板
1)C++11之前是不允许两个右尖括号出现的,会被认为是右移操作符,所以需要中间加个空格进行分割,避免发生编译错误。
int main() {
std::vector<std::vector<int>> vecA; // error
std::vector<std::vector<int> > vecB; // ok
}
2)引入了using,可以定义别名
typedef std::vector<std::vector<int>> vecA; // before c++11
using vecA= std::vector<std::vector<int>>; // c++11
3)默认函数模板参数
- 智能指针
std::shared_ptr:使用了引用计数,每一个shared_ptr的拷贝都指向相同的内存,每次拷贝都会触发引用计数+1,每次生命周期结束析构的时候引用计数-1,在最后一个shared_ptr析构的时候,内存才会释
std::weak_ptr:是用来监视shared_ptr的生命周期,它不管理shared_ptr内部的指针,它的拷贝的析构都不会影响引用计数,可以用来解决循环引用问题
std::unique_ptr:是一个独占型的智能指针,它不允许其它智能指针共享其内部指针,也不允许unique_ptr的拷贝和赋值。 - for循环
vector<int> vec;
for (auto iter = vec.begin(); iter != vec.end(); iter++) { // before c++11
cout << *iter << endl;
}
for (auto &item : vec) { // c++11基于范围的for循环
cout << item << endl;
}
- nullptr
空指针新引入的常量值,NULL本质上是个int型的0,其实不是个指针,所以判断空指针使用nullptr - 时间库chrono
1)duration表示时间段,单位有s,ms。示例:
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
2)time_point表示时间点
//获取当前时间点
std::chrono::time_point<std::chrono::high_resolution_clock> Now() {
return std::chrono::high_resolution_clock::now();
}
3)clocks表示时钟
steady_clock:相对于系统开机启动的时间,可用于计时
system_clock:系统时钟
high_resolution_clock:高精度时钟
- 正则表达式
std::regex word_regex("(\\w+)"); // 匹配字母数字字符
- 自定义字面量
std::this_thread::sleep_for(100ms);
std::this_thread::sleep_for(100s);
- 有作用域枚举
不带作用域枚举可以自动转成整型,不同枚举可以比较。示例:
enum class Color1 {
Red
};
enum class Color2 {
White
};
int main() {
if (Color1::Red == Color2::White) { // 编译失败
}
return 0;
}
- constexpr
用于编译时的常量和常量函数
constexpr int func(int i) {
return i + 1;
}
int main() {
int i = 10;
func(i);// 普通函数
func(10);// 编译期间就会被计算出来
}
- 新增数据结构
1)std::forward_list:单向链表,只允许前进
std::forward_list<int> fl = {1, 2, 3, 4, 5};
for (const auto &elem : fl) {
cout << elem;
}
2)std::unordered_set:基于hash表实现的set,内部不会排序,使用方法和set类似
3)std::unordered_map:基于hash表实现的map,内部不会排序,使用方法和set类似
4)std::array:数组
5)std::tuple:元组类型
- explicit
explicit专用于修饰构造函数,表示只能显式构造,不可以被隐式转换