C++11及其之后的新特性
C++11
- 自动类型推导
需要注意的是:
- 必须在定义时初始化auto类型的变量
- auto类型不能定义数组
- 一旦初始初始化,就不可更改类型
auto x = 5;
auto y = 3.14;
auto a; // 错误
auto array[10]; //错误
auto a = 10;
a = "ABC"; //错误
- for range循环
需要注意的是:
- 这种循环方式不能使用索引
- 基于for range循环的遍历是只读遍历,除非将变量类型声明为引用类型。
std::vector<int> v = {1, 2, 3, 4, 5};
for (auto& element : v) {
std::cout << element << " ";
}
- Lambda 表达式
利用Lambda表达式,可以方便的定义和创建匿名函数。声明格式如下:
[capture list] (params list) mutable exception-> return type { function body }
[capture list]
: 捕获外部变量列表params list
: 形参列表mutable
: 说明是否可以修改捕获的变量exception
: 异常设置return type
: 返回值类型{function body}
: 函数体
在下面示例中
auto lambda
说明为lambda类型变量, lambda不能手动指定类型[x]
为捕获外部变量列表(int a, int b)
为形参列表, 接受2个整形参数mutable
关键字, 说明可以修改捕获的变量throw()
表示声明不抛出任何异常-> int
说明返回值为一个整型值{ x += a + b; return x; }
函数体用于实现具体功能, 也就是返回x = x + (a + b)
auto lambda = [x] (int a, int b) mutable throw() -> int {
x += a + b;
return x;
};
std::cout << lambda(3, 4) << std::endl;
再写一个例子, 是一个无捕获的Lambda表达式.
这个很多人一开始看不懂, sort()
函数的第3个可选参数是排序方法 comp
, 默认情况下是升序, 当 a < b =true
时, sort()
认为 a
应该出现在 b
之前; 当 a < b = false
时, sort()
认为 b
应该出现在 a
之前或两者相等.
std::vector<int> v = {3, 1, 4, 1, 5, 9};
std::sort(v.begin(), v.end(), [](int a, int b) {
return a < b;
});
- 智能指针
std::unique_ptr<int> p1(new int(42)); // 独占所有权, 保证同一时间内只有一个智能指针可以指向该对象。
std::shared_ptr<int> p2 = std::make_shared<int>(42); // 共享所有权, 多个智能指针可以指向相同对象, 该对象和其相关资源会在最后一个引用被销毁时(计数为0)候释放
std::weak_ptr<int> p3 = p2 // weak_ptr只是提供了对管理对象的一个访问手段, 引用对象时引用计数不增加
std::weak_ptr<int> p3 = p1 // 错误, 不能指向unique_ptr
- 右值引用和移动语义
std::vector<int> v1 = {1, 2, 3};
std::vector<int> v2 = std::move(v1); // 移动语义,避免深拷贝
左值是一般指表达式结束后依然存在的持久化对象,右值指表达式结束时就不再存在的临时对象。区分左值和右值的便捷方法:能对表达式取地址、有名字的对象为左值。反之,不能取地址、匿名的对象为右值。
- 线程库
#include <thread>
void func() {
std::cout << "Hello thread!" << std::endl;
}
std::thread t(func);
t.join();
C++14
- 泛型 Lambda 表达式
C++14的泛型lambda可以被看做C++11的(单态)lambda的升级版, 可以使用 auto
关键字来创建一个可以接受任何类型参数的lambda表达式.
要注意的是:
- 泛型lambda可能接受隐式类型转换
- 表达式中的操作不支持所有可能的类型时, 类型推导错误进而导致编译错误.
auto add = [](int a, int b) { return a + b; }; // C++11
auto add = [](auto a, auto b) { return a + b; }; // C++14
- 返回类型推导
auto func() {
return 42; // 返回类型自动推导为 int
}
- 变量模板
变量模板不是变量,只有实例化的变量模板,编译器才会生成实际的变量。变量模板实例化后简单的说就是一个全局变量,所以也不用担心生存期的问题。
- 模板函数, 生成类型无关的函数
template<typename T>
T max(T a, T b) { return a > b ? a : b; }
- 模板类, 生成类型无关的类
struct Math {
static const double pi; // 声明
};
const double Math::pi = 3.14159;
- 模板变量
template<typename T>
constexpr T pi = T(3.141592653589793238462643383279);
double d = pi<double>;
float f = pi<float>;
是为了代码简洁性, 也支持编译器计算.
- 二进制字面量
以 0b
或者 0B
开头.
int a = 0b1010; // 二进制字面量 -> 十进制的 10
- std::make_unique
std::make_unique
比使用 new
更安全, 因为其可以防止内存泄露, 也可以避免裸指针.
std::unique_ptr<MyClass> ptr1(new MyClass());
std::unique_ptr<MyClass> ptr2=std::make_unique<MyClass>();
C++17
- 结构化绑定
可以把 std::pair
和 std::tuple
以及其他具有公开非静态类型的元素绑定到一组变量上. 变量类型是自动推导出来的, 不会出现类型不匹配的问题.
std::pair<int, std::string> p = {42, "hello"};
// 使用tie方法获取p中的元素
int x;
std::string y;
std::tie(x,y) = p;
// 结构化绑定方法获取p中的元素
auto [value, text] = p;
还可以用于遍历 map
以及获取有多个返回值函数的返回值:
std::map<int, std::string> m = {{1, "one"}, {2, "two"}};
for (const auto& [key, value] : m) {
std::cout << key << ": " << value << std::endl;
}
auto getPerson() {
return std::make_tuple("Alice", 30);
}
auto [name, age] = getPerson();
- constexpr if
普通的 if-else
是在执行期进行条件判断与选择, 这意味着在泛型编程中无法使用.
constexpr if
支持在编译期执行, 可以将之应用于泛型编程中的条件判断.
template<typename T>
auto get_value(T t) {
if constexpr (std::is_integral_v<T>) {
return t * 2;
} else {
return t;
}
}
- 折叠表达式
- std::optional
std::optional
表示一个可能有值的对象, 没有值时就返回 std::nullopt
.
std::optional<int> find_value() {
if (condition) {
return 42; // 有值, 返回42
} else {
return std::nullopt; // 返回nullpot
}
}
- 文件系统库
可以更方便的进行包括但不限于路径操作, 文件和目录的创建/删除/查询, 获取文件大小和系统空间信息, 目录遍历等操作.
#include <filesystem>
C++20
还没学...
- Concepts
- Coroutines 协程
- Ranges
- Modules
- 三路比较运算符<=>
参考文章
[2] C++ 11 Lambda表达式 - 滴水瓦 - 博客园
[7] 深入探索C++智能指针:std::unique_ptr、std::make_unique、std::make_shared与new的对比 - 知乎
[8] C++17尝鲜:结构化绑定声明
[9] C++17 之 "constexpr if"_c++17 constexpr if 表达式-CSDN博客
[10] 折叠表达式 | 现代 C++ 模板教程
[11] C++17 新特性之 std::optional(上) - 知乎
#C++(27)评论