2011 年发布的 C++11 被公认为"第二门语言":auto、lambda、智能指针、移动语义等特性彻底改变了写 C++ 的方式,后续 C++14/17 继续打磨。如今的主流编译器(gcc 7+、clang 5+)已完整支持 C++17,这些特性就是你的日常工具。
1. auto 与 decltype
auto 让编译器推导类型,尤其适合冗长的迭代器类型;但别滥用,可读性优先:
auto i = 42; // int
auto d = 3.14; // double
auto it = m.find("key"); // map<string,int>::iterator
// decltype:不求值,只取类型
decltype(d) x = 1.5; // x 是 double
// C++14:函数返回类型可以写 auto
auto square(double x) { return x * x; }
2. 范围 for 循环
遍历容器不再需要写迭代器,配合 auto 更简洁;要修改元素就加引用:
vector<int> v = {1, 2, 3, 4, 5};
for (int x : v) { cout << x; } // 只读
for (int& x : v) { x *= 2; } // 原地翻倍
for (const auto& item : scores) { // 只读 + 省拷贝
cout << item.first;
}
3. Lambda 表达式
就地定义匿名函数,配合算法库写"策略"非常顺手:[] 是捕获列表,() 是参数,{} 是函数体:
vector<int> v = {3, 1, 4, 1, 5, 9};
sort(v.begin(), v.end(),
[](int a, int b) { return a > b; }); // 降序
int threshold = 4;
int cnt = count_if(v.begin(), v.end(),
[threshold](int x) { return x > threshold; });
// [=] 按值捕获全部,[&] 按引用捕获全部
4. 移动语义与右值引用
右值引用 T&& 绑定临时对象,std::move 把它标记为"可移动"。移动构造"偷走"资源而不是深拷贝,性能提升显著:
class Buffer {
char* data;
public:
// 移动构造函数:接管对方的资源,把对方置空
Buffer(Buffer&& other) noexcept
: data(other.data) {
other.data = nullptr;
}
};
vector<string> v;
string big = string(1000000, 'x');
v.push_back(std::move(big)); // 移动而非拷贝,big 变空
5. nullptr 与 enum class
int* p = nullptr; // 取代 NULL,类型安全
// 强类型枚举:不会污染外层作用域,不可隐式转 int
enum class Color { Red, Green, Blue };
Color c = Color::Red;
// if (c == 0) 编译错误,必须 Color::Red
6. C++17 亮点:结构化绑定
解构返回 pair/tuple/结构体,配合 map 遍历很优雅;还有 if 初始化语句:
map<string, int> scores = {{"Alice", 95}, {"Bob", 88}};
for (const auto& [name, score] : scores) {
cout << name << ": " << score << endl;
}
// if 初始化:作用域限定在 if 内
if (auto it = scores.find("Alice"); it != scores.end()) {
cout << "找到了 " << it->second;
} // it 在这里已经失效
7. 新旧写法对照
| 旧写法 | 新写法 | 好处 |
|---|---|---|
| typedef long long ll; | using ll = long long; | 可读性、可模板化 |
| for (i=0;...) / 迭代器 | 范围 for | 不会写错边界 |
| NULL / 0 | nullptr | 类型安全 |
| 手动 new/delete | make_unique/make_shared | 异常安全 |
| 回调函数指针 | std::function + lambda | 捕获上下文 |
💡 编译时加上 -std=c++17,然后把自己写的旧代码逐段"现代化":把裸 new 换成智能指针、手写循环换成算法 + lambda。改完你会发现,同样的功能,代码更短、更不容易错。