C++98与C++11/14/17标准对比
一、C++标准演进历程
| 标准版本 | 发布年份 | 主要特性 | GCC支持 |
|---|---|---|---|
| C++98 | 1998 | 第一版C++标准 | GCC 3.x+ |
| C++11 | 2011 | 现代C++开端 | GCC 4.8+ |
| C++14 | 2014 | C++11完善版 | GCC 5.x+ |
| C++17 | 2017 | 功能增强 | GCC 8.x+ |
| C++20 | 2020 | 重大更新 | GCC 10.x+ |
1.1 版本选择建议
# 根据项目需求选择
- 老项目维护:C++98 或 C++11
- 新项目开发:C++14 或 C++17
- 前沿探索:C++20
二、核心特性对比
2.1 类型推导
C++98
// 必须显式指定类型
std::vector<int>::iterator it = vec.begin();
const std::map<std::string, int>::value_type& val = *it;
C++11/14
// 自动类型推导
auto it = vec.begin(); // std::vector<int>::iterator
const auto& val = *it; // 推导为const引用
// C++14:返回类型推导
auto add(int a, int b) {
return a + b; // 推导为int
}
2.2 智能指针
C++98
// 手动内存管理
MyClass* obj = new MyClass();
try {
obj->doSomething();
delete obj;
} catch (...) {
delete obj;
throw;
}
C++11
// 智能指针自动管理
#include <memory>
std::unique_ptr<MyClass> obj = std::make_unique<MyClass>();
obj->doSomething(); // 自动释放
对比表
| 特性 | C++98 | C++11 | C++14 |
|---|---|---|---|
| unique_ptr | ❌ | ✅ | ✅ |
| shared_ptr | ❌ | ✅ | ✅ |
| weak_ptr | ❌ | ✅ | ✅ |
| make_shared | ❌ | ✅ | ✅ |
| make_unique | ❌ | ❌ | ✅ |
2.3 Lambda表达式
C++98
// 使用函数对象
struct Printer {
void operator()(int x) {
std::cout << x << std::endl;
}
};
std::for_each(vec.begin(), vec.end(), Printer());
C++11/14
// Lambda表达式
std::for_each(vec.begin(), vec.end(), [](int x) {
std::cout << x << std::endl;
});
// C++14:泛型lambda
auto printer = [](auto x) {
std::cout << x << std::endl;
};
2.4 初始化语法
C++98
// 传统初始化
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
int arr[] = {1, 2, 3};
C++11
// 列表初始化
std::vector<int> v = {1, 2, 3};
// 统一初始化
int x{42};
std::vector<int> v2{1, 2, 3, 4};
// 防止窄化转换
int y{3.14}; // 编译错误
三、新增容器和算法
3.1 新增容器
C++11新增
#include <array>
#include <unordered_map>
#include <unordered_set>
#include <forward_list>
// array:固定大小数组
std::array<int, 5> arr = {1, 2, 3, 4, 5};
// unordered_map:哈希表
std::unordered_map<std::string, int> hashmap;
hashmap["apple"] = 10;
// forward_list:单向链表
std::forward_list<int> flist = {1, 2, 3};
容器对比
| 容器 | 特点 | 时间复杂度 |
|---|---|---|
| std::array | 固定大小,栈上分配 | O(1)访问 |
| std::vector | 动态数组 | O(1)访问,均摊O(1)插入 |
| std::list | 双向链表 | O(n)访问,O(1)插入 |
| std::forward_list | 单向链表 | O(n)访问,O(1)插入 |
| std::deque | 双端队列 | O(1)访问两端 |
| std::map | 红黑树 | O(log n)查找 |
| std::unordered_map | 哈希表 | 平均O(1)查找 |
3.2 新增算法
C++11新增算法
#include <algorithm>
// all_of, any_of, none_of
bool all_positive = std::all_of(v.begin(), v.end(),
[](int x) { return x > 0; });
// find_if_not
auto it = std::find_if_not(v.begin(), v.end(),
[](int x) { return x < 10; });
// copy_if
std::vector<int> result;
std::copy_if(src.begin(), src.end(),
std::back_inserter(result),
[](int x) { return x % 2 == 0; });
// move
std::vector<int> v2 = std::move(v1);
C++14新增
// equal, mismatch, is_permutation的谓词版本
auto eq = std::equal(v1.begin(), v1.end(),
v2.begin(), v2.end(),
[](int a, int b) { return a == b; });
四、并发支持
4.1 线程库
C++11
#include <thread>
#include <mutex>
#include <condition_variable>
// 创建线程
std::thread t([]() {
std::cout << "Hello from thread!" << std::endl;
});
t.join();
// 互斥锁
std::mutex mtx;
std::lock_guard<std::mutex> lock(mtx);
// 临界区代码
4.2 原子操作
C++11
#include <atomic>
std::atomic<int> counter(0);
// 原子递增
counter++;
// 原子读
int value = counter.load();
// 原子写
counter.store(42);
4.3 线程对比
| 特性 | POSIX线程 (C++98) | C++11线程 |
|---|---|---|
| 创建方式 | pthread_create | std::thread |
| 互斥锁 | pthread_mutex | std::mutex |
| 条件变量 | pthread_cond | std::condition_variable |
| 跨平台 | Linux主要 | 跨平台 |
| 类型安全 | ❌ | ✅ |
五、现代C++特性
5.1 右值引用和移动语义
C++11
// 移动构造函数
class MyClass {
std::vector<int> data;
public:
// 移动构造函数
MyClass(MyClass&& other) noexcept
: data(std::move(other.data)) {}
// 移动赋值运算符
MyClass& operator=(MyClass&& other) noexcept {
if (this != &other) {
data = std::move(other.data);
}
return *this;
}
};
// 使用移动语义
std::vector<MyClass> v;
v.push_back(MyClass()); // 移动而非拷贝
5.2 constexpr
C++11
// 编译期常量表达式
constexpr int square(int x) {
return x * x;
}
constexpr int result = square(5); // 编译期计算
C++14
// C++14:更宽松的constexpr
constexpr int factorial(int n) {
int result = 1;
for (int i = 1; i <= n; ++i) {
result *= i;
}
return result;
}
5.3 可变参数模板
C++11
// 可变参数模板
template<typename... Args>
void printAll(Args... args) {
(std::cout << ... << args) << std::endl; // C++17折叠表达式
}
// 使用
printAll(1, "hello", 3.14);
六、代码风格迁移
6.1 推荐使用
// ✅ 现代 C++11/14
auto vec = std::vector<int>{1, 2, 3};
auto ptr = std::make_unique<MyClass>();
for (const auto& item : vec) {
std::cout << item << std::endl;
}
6.2 避免使用
// ❌ C++98 风格
std::vector<int> vec;
vec.push_back(1);
vec.push_back(2);
for (size_t i = 0; i < vec.size(); ++i) {
std::cout << vec[i] << std::endl;
}
七、编译器支持
7.1 GCC版本支持
| GCC版本 | C++98 | C++11 | C++14 | C++17 | C++20 |
|---|---|---|---|---|---|
| GCC 4.8 | ✅ | ✅ | ⚠️ | ❌ | ❌ |
| GCC 5.x | ✅ | ✅ | ✅ | ⚠️ | ❌ |
| GCC 8.x | ✅ | ✅ | ✅ | ✅ | ⚠️ |
| GCC 10.x | ✅ | ✅ | ✅ | ✅ | ✅ |
| GCC 12.x | ✅ | ✅ | ✅ | ✅ | ✅ |
7.2 编译选项
# C++98
g++ -std=c++98 file.cpp
# C++11
g++ -std=c++11 file.cpp
# C++14
g++ -std=c++14 file.cpp
# C++17
g++ -std=c++17 file.cpp
# C++20
g++ -std=c++20 file.cpp
八、总结
8.1 核心差异
| 方面 | C++98 | C++11/14/17 |
|---|---|---|
| 类型安全 | ⚠️ | ✅ |
| 内存管理 | 手动 | 智能 |
| 并程支持 | 第三方 | 内置 |
| 性能 | 基准 | 优化 |
| 开发效率 | 中等 | 高 |
8.2 迁移建议
老项目 → 逐步迁移
↓
1. 使用智能指针替代原始指针
2. 使用auto简化代码
3. 使用range-based for循环
4. 使用lambda表达式
5. 使用现代容器和算法
8.3 最佳实践
- ✅ 新项目优先使用C++14或C++17
- ✅ 使用智能指针管理资源
- ✅ 使用RAII模式
- ✅ 使用STL容器和算法
- ✅ 使用constexpr提高性能
- ⚠️ 注意ABI兼容性问题
- ⚠️ 老项目谨慎升级