一、C++11新特性
1、auto自动类型推导
1、当类型不为引用时,auto的推导结果将不保留表达式的const属性;当类型为引用时,auto的推导结果将保留表达式的const属性。
2、C++11限制:auto不能在函数的参数中使用,不能作用于类的非静态成员变量,不能作用于模板参数,不能用于推导数组类型。还不能让普通函数具备返回值推导(C++14才行)。
2、decltype右值引用
1、作为操作符,用于查询表达式的数据类型。而auto只能用于返回变量的数据类型。
2、右值引用,也是别名,但其只能对右值引用
cpp
复制代码
//decltype关键字-推导表达式的类型,常用于模板编程
int x = 5;
decltype(x) y = x; // y 是 int
template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) {
return t + u;
}
3、移动语义 列表初始化 for each等
1、可以将资源从一个对象转移到另一个对象,这样可以减少不必要的临时对象的创建、拷贝及销毁。移动语义与拷贝语义是相对的,可以类比剪切与拷贝。在现有C++机制中,自定义的类要实现转移语义,需要定义移动构造函数,还可以定义转移赋值操作符。
2、左值:有地址、有名字的表达式(如变量)。右值:临时对象、字面量(如函数返回的局部对象),右值引用用&&表示,可以延长临时对象的生命周期。
cpp
复制代码
int x = 10; // x 是左值
int&& r = 20; //20 是右值,r 是右值引用
string getName() {
string s = "hello";
return s; //返回局部对象(右值)
}
string&& name = getName(); // 右值引用延长生命周期
//移动构造函数
class StringWrapper {
public:
//移动构造函数:转移资源,而非复制
StringWrapper(StringWrapper&& other) noexcept
: data_(other.data_), size_(other.size_) {
other.data_ = nullptr; //源对象不再拥有资源
}
private:
char* data_;
size_t size_;
};
//move:将左值转换为右值引用
vector<int> v1 = { 1, 2, 3 };
vector<int> v2 = move(v1);// v1 的资源被转移,v1变为空
//完美转发forward-在模板中保持参数的左值/右值属性
template<typename T>
void wrapper(T&& arg) {
//完美转发arg给worker,保持其值类别
worker(forward<T>(arg));
}
4、lambda
实际上是一个匿名类函数。
1、[capture-list]:捕抓列表,该列表总是出现在lambda函数的开始位置,编译器根据[]来判断接下来的代表是否为lambda函数,捕抓列表能够捕抓上下文中的变量提供lambda函数使用。
描述了上下文哪些数据可以被lambda使用,以及使用的方式传值还是传引用。
a,\&b\]其中a以复制捕获而b以引用捕获。\[this\]以引用捕获当前对象(\*this)。\[\&\]以引用捕获所有用于lambda体内的自动变量,并以引用捕获当前的对象,若存在。\[=\]以复制捕获所有用于lambda体内的自动变量,并以捕获当前对象,若存在。\[\]不捕获,大部分情况下不捕获就可以了。
2、(parameters):参数列表。与普通函数的参数列表一致,如果不需要参数传递,则可以连同()一起省略。
3、mutable:默认情况下,lambda函数总是一个const函数,mutable可以取消其常变量性,使用该修饰符时,参数列表不可省略(即使参数为空)。mutable放在参数列表和返回值之间。
4、-\>returntype:返回值类型。用追踪返回类型形式声明函数的返回值类型,没有返回值时此部分可省略。返回值类型明确情况下,也可省略,由编译器对返回类型进行推导。
5、{statement}:函数体。在该函数体内,除了可以使用其参数外,还可以使用所有捕获到的变量。(不能省略)。
```cpp
int main() {
//基本语法:[捕获列表](参数列表) -> 返回类型 { 函数体 }
vector v = { 1, 2, 3 };
sort(v.begin(), v.end(),
[](int a, int b) {return a > b; }
);
//捕获外部变量
int base = 10;
for_each(v.begin(), v.end(),
[base](int n) {cout << n + base << " "; }
);
//按值捕获 =,按引用捕获 &
auto lambda = [=](int x, int y) {return x + y; };
return 0;
}
```
> ### 5、智能指针
>
都是以模板的形式来实现的。使用时,#include\ using namespace std;
1、shared_ptr:和其他两个不同之处在于,多个shared_ptr智能指针可以共同使用同一块堆内存。并且,由于该类型智能指针在实现上采用的是引用计数机制,即便有一个shared_ptr指针放弃了堆内存的shared_ptr指针(只有引用计数为0时,堆内存才会被自动释放)。
2、unique_ptr:指针自然也具备"在合适时机自动释放堆内存空间"的能力。和shared_ptr指针最大不同之处在于,unique_ptr指针指向的堆内存无法同其它unique_ptr共享,也就是说,每个unique_ptr指针都独自拥有对其所指堆内存空间的使用权。
3、weak_ptr:shared_ptr是采用引用计数的智能指针,多个shared_ptr实例可以指向同一个动态对象,并维护了一个共享的引用计数器。对于引用计数法实现的计数,总是避免不了循环引用的问题,shared_ptr也不例外。
```cpp
//unique_ptr:独占所有权
unique_ptr p1(new int(5));
//unique_ptr p2 = p1 //错误:不能拷贝
unique_ptr p3 = move(p1);//可以移动
//shared_ptr:共享所有权(引用计数)
shared_ptr sp1 = make_shared(10);
shared_ptr sp2 = sp1;// 引用计数+1
//weak_ptr:弱引用,解决shared_ptr循环引用问题
class Node {
public:
shared_ptr next;
weak_ptr prev; //弱引用,不增加计数
};
```
> ### 6、constexpr:编译期计算
>
在编译期执行函数,提高运行效率。
```cpp
constexpr int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
int main() {
constexpr int f5 = factorial(5);//编译期计算为120
int arr[f5]; //合法:数组大小需要常量表达式
}
```
> ### 7、并发支持\
>
```cpp
void worker() {
cout << "Thread ID:" << this_thread::get_id() << endl;
}
int main() {
thread t(worker);
t.join();//等待线程结束
//原子操作
atomic counter(0);
counter.fetch_add(1);
}
```
> ### 8、其他重要特性
>
nullptr:类型安全的空指针,替代NULL
override/final:明确虚函数重写和禁止重写
=default / =delete:显式控制默认函数
static_assert:编译期断言
哈希表容器:unordered_map/unordered_set
正则表达式库\
随机表达式库\
时间库\
## 二、C++14新特性
> ### 1、泛型Lambda
>
允许lambda参数使用auto,让lambda称为模板
```cpp
//C++11:必须指定类型
auto add = [](int a, int b) {return a + b; };
//C++14:泛型lambda
auto add2 = [](auto a, auto b) {return a + b; };
```
> ### 2、Lambda捕获初始化
>
支持用任意表达式初始化捕获变量,实现移动捕获
```cpp
auto ptr = make_unique(10);
//C++14:移动捕获
auto lambda = [ptr = move(ptr)]() {
return *ptr;
};
```
> ### 3、函数返回类型推导
>
```cpp
auto add(int a, int b) {
return a + b;
}
auto getValue() {
if (true)return 1;//所有return必须推导为相同类型
else return 2;
}
```
> ### 4、decltype(auto)
>
结合decltype的推导规则和auto的语法
```cpp
int x = 5;
int& y = x;
decltype(auto) z = y; // z 是 int& (而不是 int)
```
> ### 5、constexpr增强
>
constexpr函数可以包含循环、条件语句等。
```cpp
//C++14允许循环,条件语句
constexpr int factorial(int n) {
int result = 1;
for (int i = 2; i <= n; ++i) {
result *= i;
}
return result;
}
```
> ### 6、标准库新增
>
make_unique:创建unique_ptr的工厂函数。shared_timed_mutex:共享互斥体
## 三、C++17新特性
> ### 1、结构化绑定
>
将结构体、数组、pair/tuple的成员解包到独立变量
```cpp
struct Point { int x, y; };
Point p{ 10, 20 };
auto [x, y] = p;
map m = { {1, "one"}, {2, "two"} };
int main() {
for (const auto& [key, val] : m) {
cout << key << ":" << val << endl;
}
tuple t = { 42, 3.14, "hello" };
auto [a, b, c] = t;
return 0;
}
```
> ### 2、if和switch的初始化语句
>
在条件表达式中定义变量,限制作用域。
```cpp
map mp = { {1, "one"}, {2, "two"} };
int main() {
//C++17 before
auto it = mp.find(1);
if (auto it = mp.find(1); it != mp.end()) {
//使用it
}
else {
//it仍然可以使用
}
//it超出了作用域
return 0;
}
```
> ### 3、内联变量
>
解决头文件中定义全局变量的多重定义问题。
```cpp
//头文件中,C++17可以直接定义
inline int global_counter = 0;
class MyClass {
static inline int instance_count = 0; //类内定义静态成员
};
```
> ### 4、optional
>
表示可能存在或不存在的值,替代特殊值(如-1)表示无效。
```cpp
map mp = { {1, "one"}, {2, "two"} };
optional findValue(const string & key) {
if (auto it = mp.find(key); it != mp.end())
return it->second; //返回值
return nullopt; //表示没找到
}
int main() {
auto result = findValue("key");
if (result.has_value()) {
cout << "Found:" << result.value() << endl;
}
}
```
> ### 5、variant
>
类型安全的联合体union,可存储多种类型之一。
```cpp
std::variant v;
v = 42;
v = 3.14;
v = "hello";
// 访问方式:std::visit
std::visit([](auto&& arg) {
std::cout << arg << '\n';
}, v);
```
> ### 6、string_view
>
非拥有的字符串视图,避免拷贝。
```cpp
void process(string_view sv) {
//避免了 string 的深拷贝
cout << sv.substr(0, 5);
}
string s = "very long string";
int main() {
process(s); //不拷贝
process("literal"); //直接使用字面量
return 0;
}
```
> ### 7、filesystem
>
跨平台的文件系统操作库
```cpp
fs::path p = "/home/user/file.txt";
int main() {
cout << p.filename() << endl;
cout << p.extension() << endl;
for (const auto& entry : fs::directory_iterator(".")) {
cout << entry.path() << endl;
}
return 0;
}
```
> ### 8、并行STL算法
>
支持多线程并行执行算法。
```cpp
vector v(100000);
int main() {
sort(execution::par, v.begin(), v.end());
return 0;
}
```
> ### 9、折叠表达式
>
简化可变参数模板的展开。
```cpp
template
auto sum(Args... args) {
return (args + ... + 0);//折叠表达式
}
int main() {
sum(1, 2, 3, 4);//1 + 2 + 3 + 4 = 10
}
```
> ### 10、if constexpr
>
编译期条件判断,只编译符合条件的分支
```cpp
template
auto getValue(T t) {
if constexpr (is_pointer_v) {
return *t; //仅当T是指针时编译
}
else {
return t; // 仅当T不是指针时编译
}
}
```
## 四、C++20新特性
> ### 1、Concept概念
>
对参数模板参数进行约束,提供更清晰的错误信息\[citation:9\]。
```cpp
#include
//定义概念:要求类型T支持加法
template
concept Addable = requires(T a, T b) {
{ a + b } -> same_as;
};
//使用概念约束模板参数
template
T add(T a, T b) {
return a + b;
}
int main() {
add(1, 2);
add(1.5, 2.5);//OK
//add("hello", "hello"); //错误:不满足Addable概念
}
```
### 2、范围(Ranges)
更直观、函数式风格的容器操作\[citation:9\]。
```cpp
#include
namespace views = views;
vector v = { 1, 2, 3, 4, 5, 6 };
//传统写法
vector even;
copy_if(v.begin(), v.end(), back_inserter(even),
[](int x) {return x % 2 == 0; });
//Ranges 写法:链式调用
auto result = v
| views::filter([](int x) {return x % 2 == 0; }) //过滤偶数
| views::transform([](int x) {return x * x; }) //求平方
| views::take(2); //取前两个
```
### 3、携程
支持异步编程,可暂停和恢复的函数。
### 4、三向比较运算符(\<=\>)
```cpp
struct Point {
int x, y;
//自动生成所有比较运算符(==,!=,<,<=,>,>=)
auto operator<=>(const Point&)const = default;
};
int main() {
Point p1{ 1, 2 }, p2{ 1, 3 };
cout << (p1 < p2); //true,因为y比较
return 0;
}
```
### 5、模块(Modules)
替代头文件的现代化编译单元,加快编译速度\[citation:9\]。
```cpp
//math.ixx
export module math;
export int add(int a, int b) {
return a + b;
}
//main.cpp
import math;//不再需要 #include
int main() {
return add(3, 4);
}
```
### 6、格式化库(format)
类型安全的,类似python的字符串格式化。
```cpp
#include
string s = format("Hello, {}! The answer is {}", "world", 42);
//s = "Hello, world! The answer is 42"
//位置参数
string s2 = format("{1} {0}", "world", "Hello");//"Hello world"
```
### 7、span
非拥有的连续序列视图,比指针+长度更安全。
```cpp
#include
void process(span buffer) {
for (int& x : buffer) {
x *= 2;
}
}
int main() {
vector vec = { 1, 2, 3, 4 };
process(vec);//传递vector
int arr[] = { 5, 6, 7, 8 };
process(arr);//传递数组
return 0;
}
```
## 五、C++23
在C++20上做了小幅度改进和改善。
主要特性
expected:带错误信息的返回值类型
mdspan:多维数组视图
print/println:更简洁的输出函数
Ranges库的增强:ranges::to等性新功能
this推导:允许lambda使用显式this参数
stacktrace:栈追踪支持
标准库模块import std:一站式导入标准库