前言:目前C++23版本已问世,但尚未普及,只在前沿技术验证应用居多。我们平时项目开发中仍然以主流的C++11为主,C++11可以说是现代C++的"分水岭",引入了许多新特性,大大提高了编程效率和代码性能。本文就C++11的新特性做一些分析与总结。
目录
[1.1 自动类型推导(auto)](#1.1 自动类型推导(auto))
[1.2 范围for循环](#1.2 范围for循环)
[1.3 强类型枚举(enum class)](#1.3 强类型枚举(enum class))
[1.4 nullptr空指针常量](#1.4 nullptr空指针常量)
[2.1 智能指针](#2.1 智能指针)
[2.2 右值引用与移动语义](#2.2 右值引用与移动语义)
[3.1 Lamda表达式](#3.1 Lamda表达式)
[3.2 constexpr常量表达式](#3.2 constexpr常量表达式)
一、核心语法升级
1.1 自动类型推导(auto)
编译器能够根据右侧表达式自动推导变量类型,避免冗长的类型名书写,尤其适配 STL 容器迭代器、模板类型等场景。
示例:
cpp
#include <iostream>
#include <vector>
#include <map>
int main() {
// 基础类型推导
auto num = 10; // 推导为int
auto pi = 3.14159; // 推导为double
auto str = "hello"; // 推导为const char*
// STL容器迭代器(最常用场景)
std::map<std::string, int> score_map = {{"math", 90}, {"chinese", 85}};
// C++11之前: std::map<std::string, int>::iterator it = score_map.begin();
auto it = score_map.begin(); // 简化了迭代器声明
std::cout << it->first << ": " << it->second << std::endl;
return 0;
}
1.2 范围for循环
替代传统的迭代器遍历,直接遍历容器 / 数组的每个元素,代码更简洁易读。
示例:
cpp
#include <iostream>
#include <vector>
int main() {
std::vector<int> nums = {1, 2, 3, 4, 5};
// 只读遍历
for (auto num : nums) {
std::cout << num << " "; // 输出1 2 3 4 5
}
std::cout << std::endl;
// 修改元素(加&引用)
for (auto& num : nums) {
num *= 2; // 每个元素乘2
}
// 再次遍历验证
for (const auto& num : nums) { // const&避免拷贝,提升效率
std::cout << num << " "; // 输出2 4 6 8 10
}
return 0;
}
1.3 强类型枚举(enum class)
解决传统枚举的 "作用域污染""隐式类型转换" 问题,枚举值是强类型、作用域隔离。
示例:
cpp
#include <iostream>
// 传统枚举:作用域全局,易冲突,可隐式转int
enum Color { Red, Green, Blue };
// C++11强类型枚举:作用域隔离,强类型
enum class Direction { Left, Right, Up, Down };
int main() {
// 传统枚举:可直接用Red,且能转int
Color c = Red;
std::cout << c << std::endl; // 输出0
// 强类型枚举:必须加作用域,不可隐式转int
Direction d = Direction::Left;
// std::cout << d << std::endl; // 编译报错:无重载的<<运算符
// 如需输出,需手动重载运算符
return 0;
}
1.4 nullptr空指针常量
解决NULL( 本质是0)的类型歧义问题,nullptr 是专属的空指针类型(std::nullptr_t),类型更安全。
示例:
cpp
#include <iostream>
void func(int) {
std::cout << "调用int版本" << std::endl;
}
void func(char*) {
std::cout << "调用char*版本" << std::endl;
}
int main() {
// C++98: NULL会匹配int版本(因为NULL是0),不符合预期
func(NULL); // 输出"调用int版本"
// C++11: nullptr精准匹配指针版本
func(nullptr); // 输出"调用char*版本"
return 0;
}
二、面向对象与内存管理
2.1 智能指针
借鉴类的构造析构原理,将指针封装成类的形式,自动管理动态内存,彻底解决内存泄漏问题(RAII 机制),替代裸指针。智能指针详细解读可参考:C++智能指针 解读_cpp 智能指针-CSDN博客
示例:
cpp
#include <iostream>
#include <memory>
class MyClass {
public:
MyClass() { std::cout << "构造函数" << std::endl; }
~MyClass() { std::cout << "析构函数" << std::endl; }
void show() { std::cout << "MyClass::show()" << std::endl; }
};
int main() {
// 1. unique_ptr:独占所有权,不可拷贝,可移动
std::unique_ptr<MyClass> uptr(new MyClass());
uptr->show();
// std::unique_ptr<MyClass> uptr2 = uptr; // 编译报错:禁止拷贝
std::unique_ptr<MyClass> uptr2 = std::move(uptr); // 移动语义,uptr变为空
// 2. shared_ptr:共享所有权,引用计数
std::shared_ptr<MyClass> sptr = std::make_shared<MyClass>(); // 推荐make_shared(更高效)
std::shared_ptr<MyClass> sptr2 = sptr; // 引用计数+1
std::cout << "引用计数:" << sptr.use_count() << std::endl; // 输出2
// 3. weak_ptr:弱引用,不增加引用计数,解决shared_ptr循环引用问题
std::weak_ptr<MyClass> wptr = sptr;
if (auto ptr = wptr.lock()) { // 检查指针是否有效
ptr->show();
}
return 0; // 智能指针自动析构,调用~MyClass()
}
2.2 右值引用与移动语义
右值引用是移动语义的基础,移动语义是为了避免深拷贝,直接 "转移" 临时对象的资源,大大提升效率。详细解读可参考:C++ 右值引用与移动语义-CSDN博客
三、函数式编程与泛型增强
3.1 Lamda表达式
定义临时的匿名函数,无需单独声明函数,适配std 算法(如std::sort )等。Lamda表达式详细解读可参考:C++ Lambda表达式-CSDN博客
示例:
cpp
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> nums = {3, 1, 4, 1, 5, 9};
// 1. 排序:用Lambda自定义排序规则(降序)
std::sort(nums.begin(), nums.end(), [](int a, int b) {
return a > b; // 降序排序
});
// 2. 遍历:for_each结合Lambda
std::for_each(nums.begin(), nums.end(), [](int num) {
std::cout << num << " "; // 输出9 5 4 3 1 1
});
std::cout << std::endl;
return 0;
}
3.2 constexpr常量表达式
使得变量 / 函数在编译期就可以确定其值或结果,而非运行期,提升程序执行效率。
示例:
cpp
#include <iostream>
// constexpr函数:编译期计算
constexpr int square(int x) {
return x * x;
}
int main() {
// constexpr变量:编译期确定值
constexpr int max_num = 100;
constexpr int s = square(6); // 编译期计算6*6=36
std::cout << s << std::endl; // 输出36
return 0;
}