Modern Cpp
是从1.0版本移植过来的,但经过了gemini老师的润色和补充。
Modern C++ Overview: 从底层逻辑到语法糖
前言:上机课偶遇 Modern C++,拼劲全力无法战胜?在习惯了 Java 的自动内存管理和 Python 的灵活后,C++ 的语法规则确实显得复杂(甚至有些诡异)。
关于 C++ 的刻板印象 (Stereotypes):
- Old, out-dated, less-frequently used
- Unsafe (最大的痛点,内存泄露和越界)
- Hard to use & Various Compilation Issues
尽管如此,我们仍然需要学习 Modern C++,因为它在系统编程和高性能领域依然是无可替代的。
1. Value Types & Move Semantics (值类型与移动语义)
左值 (lvalue) vs 右值 (rvalue)
- 左值 (lvalue):表示占据内存中某个可识别位置(也就是一个地址)的对象。可以使用
&取地址。 - 右值 (rvalue):与之相反,通常是临时对象,不可以使用
&取地址。
拷贝赋值 vs 移动赋值
对于赋值操作 a = xxx:
- 拷贝赋值 (Copy Assignment):当
xxx为左值时调用。 - 移动赋值 (Move Assignment):当
xxx为右值时调用。
std::move
一个常识是:移动 (Move) 比拷贝 (Copy) 快。如果我们想移动一个左值呢?
我们可以使用 std::move。它让编译器认为某个左值是一个右值,从而实现所有权的转移。
注意:使用了
std::move后的对象不可再使用;此外,const变量不可使用移动语义。
❌ 不可使用 std::move 的常见错误场景:
1 | void Print(const std::string &s); |
2. Type Inference & std::forward (类型推导与完美转发)
Universal Reference (万能引用)
在模板中,T&& 并不总是代表右值引用,它可能是万能引用。它既可以接收左值,也可以接收右值。
1 | template<typename T> |
3. Smart Pointers (智能指针)
Modern C++ 通过智能指针管理内存,遵循 RAII 原则,彻底告别裸指针。
std::unique_ptr
核心属性:独占所有权,不可拷贝(Copy Forbidden),只能移动(Move Only)。
用法:使用 std::make_unique
std::shared_ptr
核心属性:多个所有者共享同一个资源。
引用计数:通过 control block 记录当前有多少个指针指向该对象,计数归零时自动释放。
std::weak_ptr (解决循环引用)
如果 A 指向 B,B 也指向 A(都是 shared_ptr),就会形成死锁。weak_ptr 不增加引用计数,可以观测对象但不会延长其生命周期。
1 | struct Node { |
4. Syntax Sugar (语法糖)
auto 推断
auto 会自动推导变量类型,让代码更简洁,特别是处理迭代器或复杂模板时。
1 | std::vector<int> vec = {1, 2, 3}; |
结构化绑定 (Structured Bindings - C++17)
一次性从 std::pair 或 std::tuple 中提取多个变量。
1 | std::map<std::string, int> scores = {{"Alice", 90}}; |
5. Safety (C++17 安全容器)
为了避免使用不安全的 union 或容易导致错误的空指针。
std::any
可以存储任何类型的值,但在访问时必须通过 any_cast 进行类型安全检查。
std::optional
表示一个可能为空的值。不再需要通过返回 -1 或 nullptr 来表达“无效”。
1 | std::optional<int> getValue(bool success) { |
std::variant
类型安全的 union。它知道自己当前存的是哪种类型,并能通过 std::visit 优雅地处理。
1 | using MyType = std::variant<int, std::string>; |
