C++11新特性
C++11新特性
《C++ Primer Plus》笔记
统一的初始化
使用大括号进行初始化
使用大括号形式不能进行缩窄形式的类型转化
int x = {5};
double y{3.14};
short a[]{5, 4, 3, 2, 1};
int *ar = new int[4] {10, 9, 8, 7};
char c = {459585821}; // 非法初始化
声明变量
auto
auto a = 10; // 自动推断为int类型
auto b = vec.begin(); // 自动推断为vector::iterator类型
decltype
将变量类型声明为表达式指定类型
double x = 2.3;
int y = 1;
decltype(x * y) q; // 将q声明为x*y的结果相同的类型
智能指针
auto_ptr | 已被C++11摒弃 |
unique_ptr | 只能是一个指针指向一个对象 |
shared_ptr | 多个指针指向一个对象 |
异常相关
提出了新关键字
noexcept
,表示不会抛出异常
void fun() noexcept {
}
作用域内枚举
使用class或struct关键字定义枚举,使用时加上作用域名称
enum class Color{red, yellow, green, blue};
auto x = Color::red;
显示转换运算符
explicit
关键字防止类构造函数使用自动转换,C++11扩展到可以对转换函数使用
class Plebe {
...
operator int();
explicit operator double();
}
Plebe a, b;
int n = a;
double x = b; // 非法转换
double x = double(b);
STL修改
新增新的for循环方法和若干STL容器类
右值引用
在引用中,无法对右值添加引用
int num = 10;
int &a = num; // 支持
int &b = 10; // 报错
右值引用使用
&&
int num = 10;
int &&a = num; // 右值引用不能初始胡为左值
int &&b = 10; // 支持
移动语义
移动语义避免移动原始数据,而只是修改记录,使用右值引用实现
移动构造函数
将原对象中的数据移动到新的对象中,而不是进行深拷贝
当类中同时存在拷贝构造函数和移动构造函数时,如果使用临时对象初始化当前的类对象,则有限调用移动构造,若没有移动构造函数,则调用拷贝构造函数。
class Test {
private:
int n;
char* str;
public:
Test(int n, char* str);
// 普通的复制构造函数
Test(Test t);
// 移动构造函数
Test(Test&& t);
Test operator +(const Test& t) const;
}
Test::Test(Test t) {
n = t.n;
str = new char[n];
for(int i = 0; i < n; i++) {
str[i] = t.str[i];
}
}
Test::Test(Test&& t) {
n = t.n;
str = t.str;
t.str = nullptr;
f.n = 0;
}
Test a(3,"abc");
Test b = a; // 调用拷贝构造函数
Test c = a + b; //调用移动构造函数
移动赋值运算符
类似于移动构造函数
虚方法管理
override
override
指出需要覆盖的虚函数,放在参数列表后面,如果声明与基类方法不匹配,则报错
final
final
指出该方法不能被被派生类覆盖
Lambda表达式
Lambda语法
// []表示Lambda函数外的变量,()表示形参,{}表示函数体
[&count](int x){count += (x % 13 == 0);}
auto f = [](int x) {return x == 13;};
bool res = f(a);
包装器(适配器)
下面的代码中,模板函数会生成3个实例化方法,导致效率低下
template<class T, class F>
T void use_f(T v, F f) {
return f(v);
}
void fun1(double x) {
return x + 1;
}
void fun2(double x) {
return x * 2;
}
class Class1 {
publc:
double operator()(double x) {
return x + 1;
}
}
class Class2 {
publc:
double operator()(double x) {
return x * 2;
}
}
double x = 1.0;
double x1 = use_f(x, fun1); // use_f(double, double(*)(double))
double x2 = use_f(x, fun2); // use_f(double, double(*)(double))
double x3 = use_f(x, Class1()); // use_f(double, Class1)
double x4 = use_f(x, Class2()); // use_f(double, Class2)
使用包装器
function
只会生成一种实例化方法
template<class T>
bool fun(T v, std::Function<bool(int)> f) {
return f(v);
}
std::function<double(double)> f = [](double x) {return x * 2;};
double x = 1.0;
// use_f(double, std::function<double(double)>)
double x1 = use_f(x, fun1);
double x2 = use_f(x, fun2);
double x3 = use_f(x, Class1());
double x4 = use_f(x, Class2());