在产品项目中,一般不会(也不应该)全局使用 using namespace std
1. 易用性改进
1.1 类型推导auto & decltype
关键字:auto, decltype , 在编译期推导出变量或者表达式的类型,方便编码或简化代码;
auto a = 10;// 10是int型,可以自动推导出a是int
for (auto it = v.begin(), end = v.end();
it != end; ++it) {
// 循环体
}
decltype:相对于auto用于推导变量类型,而decltype则用于推导表达式类型,这里只用于编译器分析表达式的类型,表达式实际不会进行运算
cont int &i = 1;
int a = 2;
decltype(i) b = 2; // b是const int&
1.2 列表初始化
在 C++98 里,标准容器比起 C 风格数组至少有一个明显的劣势:不能在代码里方便地初始化容器的内容。
如:
int a[] = {1, 2, 3, 4, 5};
而对于 vector 你却得写:
vector<int> v;
v.push(1);
v.push(2);
v.push(3);
v.push(4);
v.push(5);
使用初始化列表:
vector<int> v{1, 2, 3, 4, 5};
例子:
https://en.cppreference.com/w/cpp/utility/initializer_list
https://en.cppreference.com/w/cpp/utility/initializer_list
1.3 模板的改进
1.4 统一初始化
C++11 引入的新语法,能够代替很多小括号 () 在变量初始化时使用。这被称为统一初始化(uniform initialization)。
大括号对于构造一个对象而言,最大的好处是避免了 C++ 里“最令人恼火的语法分析”(the most vexing parse)。
1.5 类数据成员的默认初始化
按照 C++98 的语法,数据成员可以在构造函数里进行初始化。这本身不是问题,但实践中,如果数据成员比较多、构造函数又有多个的话,逐个去初始化是个累赘,并且很容易在增加数据成员时漏掉在某个构造函数中进行初始化。为此,C++11 增加了一个语法,允许在声明数据成员时直接给予一个初始化表达式。这样,当且仅当构造函数的初始化列表中不包含该数据成员时,这个数据成员就会自动使用初始化表达式进行初始化。
1.6 自定义字面量
https://en.cppreference.com/w/cpp/language/user_literal
-
二进制字面量
你一定知道 C++ 里有 0x 前缀,可以让开发人员直接写出像 0xFF 这样的十六进制字面量。另外一个目前使用得稍少的前缀就是 0 后面直接跟 0–7 的数字,表示八进制的字面量,在跟文件系统打交道的时候还会经常用到:有经验的 Unix 程序员可能会觉得 chmod(path, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) 并不比 chmod(path, 0644) 更为直观。从 C++14 开始,我们对于二进制也有了直接的字面量
unsigned mask = 0b111000000; -
数字分隔符
数字长了之后,看清位数就变得麻烦了。有了二进制字面量,这个问题变得分外明显。C++14 开始,允许在数字型字面量中任意添加 ' 来使其更可读。
具体怎么添加,完全由程序员根据实际情况进行约定。
某些常见的情况可能会是:
十进制数字使用三位的分隔,对应英文习惯的 thousand、million 等单位。
十进制数字使用四位的分隔,对应中文习惯的万、亿等单位。
十六进制数字使用两位或四位的分隔,对应字节或双字节。
二进制数字使用三位的分隔,对应文件系统的权限分组
例如:
unsigned mask = 0b111'000'000;
long r_earth_equatorial = 6'378'137;
double pi = 3.14159'26535'89793;
const unsigned magic = 0x44'42'47'4E;
1.7 静态断言
语法:
static_assert(编译期条件表达式,
可选输出信息);
示例:
static_assert((alignment & (alignment - 1)) == 0,
"Alignment must be power of two");
1.8 default和delete成员函数
default : 当存在用户定义的构造函数时,用户仍可以通过关键词 default 强制编译器自动生成原本隐式声明的默认构造函数
1.9 override 和 final 说明符
- override
显式声明了成员函数是一个虚函数且覆盖了基类中的该函数。
如果有 override 声明的函数不是虚函数,或基类中不存在这个虚函数,编译器会报告错误。这个说明符的主要作用有两个:
- 给开发人员更明确的提示,这个函数覆写了基类的成员函数;
- 让编译器进行额外的检查,防止程序员由于拼写错误或代码改动没有让基类和派生类中的成员函数名称完全一致。
- final
则声明了成员函数是一个虚函数,且该虚函数不可在派生类中被覆盖。如果有一点没有得到满足的话,编译器就会报错。
final 还有一个作用是标志某个类或结构不可被派生。同样,这时应将其放在被定义的类或结构名后面。
示例:
class A {
public:
virtual void foo();
virtual void bar();
void foobar();
};
class B : public A {
public:
void foo() override; // OK
void bar() override final; // OK
//void foobar() override;
// 非虚函数不能 override
};
class C final : public B {
public:
void foo() override; // OK
//void bar() override;
// final 函数不可 override
};
class D : public C {
// 错误:final 类不可派生
…
};
1.20 nullptr
nullptr是c++11用来表示空指针新引入的常量值,在c++中如果表示空指针语义时建议使用nullptr而不要使用NULL,因为NULL本质上是个int型的0,其实不是个指针。
1.21 explicit
explicit专用于修饰构造函数,表示只能显式构造,不可以被隐式转换
1.22 constexpr
1.23 基于范围的for循环
for (declaration : expression){
//循环体
}
for (auto ch : myvector) {
cout << ch;
}
6. 委托构造函数
7. 继承构造函数
8. enum class
c++11新增有作用域的枚举类型
9. 非受限联合体
c++11之前union中数据成员的类型不允许有非POD类型,而这个限制在c++11被取消,允许数据成员类型有非POD类型
10. sizeof
c++11中sizeof可以用的类的数据成员上
12. 内存对齐
14. 基础数值类型
c++11新增了几种数据类型: long long 、char16_t、char32_t等
15. 随机数功能
c++11关于随机数功能则较之前丰富了很多,典型的可以选择概率分布类型
16. 正则表达式
17.chrono
c++11关于时间引入了chrono库,源于boost,功能强大,chrono主要有三个点:
duration
time_point
clocks
18. 并发
c++11关于并发引入了好多好东西,有:
std::thread相关
std::mutex相关
std::lock相关
std::atomic相关
std::call_once相关
volatile相关
std::condition_variable相关
std::future相关
async相关
19. thread_local
c++11引入thread_local,用thread_local修饰的变量具有thread周期,每一个线程都拥有并只拥有一个该变量的独立实例,一般用于需要保证线程安全的函数中
参考资料:
https://cloud.tencent.com/developer/article/1745592
https://zh.cppreference.com/w/%E9%A6%96%E9%A1%B5
网友评论