Skip to content

C++ 语言标准

C++ 标准概述

C++ 语言由 ISO/IEC 标准化,每个版本都引入了新的特性和改进。

版本发布年份正式名称主要特性
C++981998ISO/IEC 14882:1998第一个标准
C++032003ISO/IEC 14882:2003C++98 的技术勘误
C++112011ISO/IEC 14882:2011重大更新(现代 C++)
C++142014ISO/IEC 14882:2014C++11 的小更新
C++172017ISO/IEC 14882:2017主要增强
C++202020ISO/IEC 14882:2020新特性(模块、协程等)
C++232023ISO/IEC 14882:2023最新标准

C++11(现代 C++)

类型推断

cpp
// auto 关键字
auto x = 42;                    // int
auto y = 3.14;                  // double
auto z = "hello";               // const char*
auto vec = std::vector<int>();  // std::vector<int>

// decltype
int a = 10;
decltype(a) b = 20;  // int

// 返回类型推断
auto add(int x, int y) -> int {
    return x + y;
}

智能指针

cpp
#include <memory>

// unique_ptr - 独占所有权
std::unique_ptr<int> ptr1 = std::make_unique<int>(42);
// std::unique_ptr<int> ptr2 = ptr1;  // 错误:不能复制
std::unique_ptr<int> ptr2 = std::move(ptr1);  // 可以移动

// shared_ptr - 共享所有权
std::shared_ptr<int> sp1 = std::make_shared<int>(42);
std::shared_ptr<int> sp2 = sp1;  // 多个指针共享所有权
std::cout << sp1.use_count() << std::endl;  // 2

// weak_ptr - 弱引用,不增加引用计数
std::weak_ptr<int> wp = sp1;
if (auto locked = wp.lock()) {
    std::cout << *locked << std::endl;
}

Lambda 表达式

cpp
// 基本语法
auto lambda = [](int x) { return x * x; };
int result = lambda(5);  // 25

// 带捕获
int multiplier = 2;
auto multiply = [multiplier](int x) { return x * multiplier; };

// 可变捕获
int counter = 0;
auto increment = [counter]() mutable {
    counter++;
    return counter;
};

// 在算法中使用
std::vector<int> numbers = {1, 2, 3, 4, 5};
std::for_each(numbers.begin(), numbers.end(), [](int& x) {
    x *= 2;
});

// 带谓词
std::sort(numbers.begin(), numbers.end(), [](int a, int b) {
    return a > b;  // 降序排序
});

右值引用和移动语义

cpp
// 右值引用
int&& rref = 42;

// 移动构造函数
class Resource {
private:
    int* data;
    size_t size;
    
public:
    Resource(size_t s) : size(s), data(new int[s]) {}
    
    // 移动构造函数
    Resource(Resource&& other) noexcept : size(other.size), data(other.data) {
        other.data = nullptr;
        other.size = 0;
    }
    
    // 移动赋值运算符
    Resource& operator=(Resource&& other) noexcept {
        if (this != &other) {
            delete[] data;
            data = other.data;
            size = other.size;
            other.data = nullptr;
            other.size = 0;
        }
        return *this;
    }
    
    ~Resource() {
        delete[] data;
    }
};

// std::move
Resource createResource() {
    return Resource(100);
}

Resource r1 = createResource();  // 移动构造
Resource r2 = std::move(r1);     // 显式移动

范围 for 循环

cpp
std::vector<int> numbers = {1, 2, 3, 4, 5};

// 只读访问
for (int num : numbers) {
    std::cout << num << " ";
}

// 修改元素
for (int& num : numbers) {
    num *= 2;
}

// 使用 auto
for (const auto& num : numbers) {
    std::cout << num << " ";
}

// 初始化列表
for (auto x : {1, 2, 3, 4, 5}) {
    std::cout << x << " ";
}

新容器

cpp
#include <array>
#include <unordered_map>
#include <unordered_set>
#include <tuple>

// array - 固定大小数组
std::array<int, 5> arr = {1, 2, 3, 4, 5};

// unordered_map - 哈希表
std::unordered_map<std::string, int> hashmap;
hashmap["apple"] = 1;
hashmap["banana"] = 2;

// unordered_set - 哈希集合
std::unordered_set<int> hashset;
hashset.insert(1);
hashset.insert(2);

// tuple - 元组
std::tuple<int, double, std::string> myTuple(42, 3.14, "hello");
int first = std::get<0>(myTuple);
double second = std::get<1>(myTuple);
std::string third = std::get<2>(myTuple);

// 结构化绑定(C++17)
auto [i, d, s] = myTuple;

线程支持

cpp
#include <thread>
#include <mutex>
#include <future>

// 创建线程
void worker(int id) {
    std::cout << "Worker " << id << std::endl;
}

std::thread t1(worker, 1);
std::thread t2(worker, 2);
t1.join();
t2.join();

// 互斥锁
std::mutex mtx;
int counter = 0;

void increment() {
    std::lock_guard<std::mutex> lock(mtx);
    counter++;
}

// 异步操作
std::future<int> future = std::async(std::launch::async, [](){
    return 42;
});
int result = future.get();

其他特性

cpp
// nullptr 代替 NULL
int* ptr = nullptr;

// constexpr - 编译时常量
constexpr int factorial(int n) {
    return (n <= 1) ? 1 : n * factorial(n - 1);
}
constexpr int result = factorial(5);  // 120

// noexcept - 不抛出异常
void safeFunction() noexcept {
    // 保证不会抛出异常
}

// override 和 final
class Base {
public:
    virtual void func() {}
};

class Derived : public Base {
public:
    void func() override {}  // 明确覆盖
};

// = delete 和 = default
class MyClass {
public:
    MyClass() = default;          // 使用默认构造函数
    MyClass(const MyClass&) = delete;  // 禁止拷贝构造
};

C++14

泛型 lambda

cpp
// C++11
auto lambda = [](int x, int y) { return x + y; };

// C++14 - 自动推断参数类型
auto genericLambda = [](auto x, auto y) {
    return x + y;
};

int sum1 = genericLambda(1, 2);           // int
double sum2 = genericLambda(1.5, 2.5);    // double

返回类型推断

cpp
// C++11
auto add(int x, int y) -> int {
    return x + y;
}

// C++14 - 自动推断返回类型
auto add(int x, int y) {
    return x + y;
}

make_unique

cpp
// C++11
std::unique_ptr<int> ptr(new int(42));

// C++14 - 更安全的方式
auto ptr = std::make_unique<int>(42);

二进制字面量

cpp
int binary = 0b1010;  // 10
int octal = 0o755;    // 八进制字面量

变量模板

cpp
template<typename T>
constexpr T pi = T(3.1415926535897932385L);

int intPi = pi<int>;
double doublePi = pi<double>;

C++17

结构化绑定

cpp
std::pair<int, std::string> pair = {42, "hello"};
auto [num, str] = pair;

std::tuple<int, double, std::string> tuple = {42, 3.14, "world"};
auto [i, d, s] = tuple;

// 在范围 for 循环中使用
std::map<std::string, int> map = {{"a", 1}, {"b", 2}};
for (const auto& [key, value] : map) {
    std::cout << key << ": " << value << std::endl;
}

if constexpr

cpp
template<typename T>
auto get_value(T t) {
    if constexpr (std::is_pointer_v<T>) {
        return *t;  // 如果是指针
    } else {
        return t;   // 如果不是指针
    }
}

int x = 42;
int* ptr = &x;

std::cout << get_value(x) << std::endl;   // 42
std::cout << get_value(ptr) << std::endl; // 42

std::optional

cpp
#include <optional>

std::optional<int> divide(int a, int b) {
    if (b == 0) {
        return std::nullopt;  // 无效值
    }
    return a / b;
}

auto result = divide(10, 2);
if (result) {
    std::cout << *result << std::endl;  // 5
}

result = divide(10, 0);
if (!result) {
    std::cout << "Division by zero!" << std::endl;
}

std::variant

cpp
#include <variant>

std::variant<int, double, std::string> value;

value = 42;
std::cout << std::get<int>(value) << std::endl;

value = 3.14;
if (std::holds_alternative<double>(value)) {
    std::cout << std::get<double>(value) << std::endl;
}

value = "hello";
std::visit([](auto&& arg) {
    std::cout << arg << std::endl;
}, value);

std::any

cpp
#include <any>

std::any value = 42;
value = 3.14;
value = "hello";

if (value.type() == typeid(std::string)) {
    std::string str = std::any_cast<std::string>(value);
    std::cout << str << std::endl;
}

并行算法

cpp
#include <algorithm>
#include <execution>

std::vector<int> numbers(1000000);
std::iota(numbers.begin(), numbers.end(), 1);

// 并行排序
std::sort(std::execution::par, numbers.begin(), numbers.end());

// 并行 for_each
std::for_each(std::execution::par, numbers.begin(), numbers.end(),
              [](int& x) { x *= 2; });

文件系统

cpp
#include <filesystem>
namespace fs = std::filesystem;

// 检查文件是否存在
if (fs::exists("test.txt")) {
    std::cout << "File exists" << std::endl;
}

// 创建目录
fs::create_directory("new_folder");

// 复制文件
fs::copy_file("source.txt", "destination.txt");

// 遍历目录
for (const auto& entry : fs::directory_iterator(".")) {
    std::cout << entry.path() << std::endl;
}

// 获取文件大小
if (fs::is_regular_file("test.txt")) {
    auto size = fs::file_size("test.txt");
    std::cout << "File size: " << size << " bytes" << std::endl;
}

std::string_view

cpp
#include <string_view>

void printString(std::string_view sv) {
    std::cout << sv << std::endl;
}

std::string str = "hello";
printString(str);          // 从 std::string
printString("world");      // 从字符串字面量
printString(str.substr(0, 3));  // 从子串

C++20

模块

cpp
// math.ixx - 模块接口
export module math;

export int add(int a, int b) {
    return a + b;
}

export double multiply(double a, double b) {
    return a * b;
}

// main.cpp
import math;
#include <iostream>

int main() {
    std::cout << add(1, 2) << std::endl;
    std::cout << multiply(2.0, 3.0) << std::endl;
    return 0;
}

协程

cpp
#include <coroutine>
#include <iostream>

struct Task {
    struct promise_type {
        Task get_return_object() {
            return {};
        }
        std::suspend_never initial_suspend() { return {}; }
        std::suspend_never final_suspend() noexcept { return {}; }
        void return_void() {}
        void unhandled_exception() {}
    };
};

Task coroutine() {
    std::cout << "Coroutine start" << std::endl;
    co_await std::suspend_always{};
    std::cout << "Coroutine resume" << std::endl;
}

int main() {
    auto task = coroutine();
    return 0;
}

Concepts(概念)

cpp
#include <concepts>

template<typename T>
concept Integral = std::is_integral_v<T>;

template<Integral T>
T add(T a, T b) {
    return a + b;
}

// 或使用 requires
template<typename T>
requires std::is_integral_v<T>
T multiply(T a, T b) {
    return a * b;
}

// 使用 requires 子句
auto print = [](const auto& container) requires requires {
    { container.size() } -> std::convertible_to<size_t>;
} {
    std::cout << container.size() << std::endl;
};

范围

cpp
#include <ranges>
#include <vector>
#include <algorithm>

std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

// 过滤偶数
auto evens = numbers | std::views::filter([](int x) {
    return x % 2 == 0;
});

// 转换为平方
auto squares = numbers | std::views::transform([](int x) {
    return x * x;
});

// 组合视图
auto result = numbers 
    | std::views::filter([](int x) { return x % 2 == 0; })
    | std::views::transform([](int x) { return x * x; });

for (int x : result) {
    std::cout << x << " ";
}

三向比较(Spaceship 运算符)

cpp
#include <compare>

struct Point {
    int x, y;
    
    auto operator<=>(const Point&) const = default;
};

Point p1{1, 2};
Point p2{1, 3};

if (p1 < p2) {
    std::cout << "p1 < p2" << std::endl;
}

std::span

cpp
#include <span>

void printArray(std::span<int> arr) {
    for (int x : arr) {
        std::cout << x << " ";
    }
    std::cout << std::endl;
}

int main() {
    int arr1[] = {1, 2, 3, 4, 5};
    std::vector<int> vec = {1, 2, 3, 4, 5};
    
    printArray(arr1);      // 从 C 数组
    printArray(vec);       // 从 vector
    printArray({1, 2, 3}); // 从初始化列表
    
    return 0;
}

其他特性

cpp
// consteval - 强制编译时求值
consteval int square(int x) {
    return x * x;
}
constexpr int result = square(5);  // OK
// int runtimeValue = square(5);   // 错误

// constinit - 常量初始化
constinit int globalVar = 42;

// 设计初始化符
struct Point {
    int x, y;
};

Point p1{.x = 1, .y = 2};  // 指定成员初始化

// 范围 for 循环初始化
std::vector<int> vec;
for (auto x : vec = {1, 2, 3, 4, 5}) {
    std::cout << x << " ";
}

C++23

标准库模块

cpp
import std;

int main() {
    std::cout << "Hello, World!" << std::endl;
    return 0;
}

Deducing this(推断 this)

cpp
struct Widget {
    void print() const & {
        std::cout << "Lvalue" << std::endl;
    }
    
    void print() && {
        std::cout << "Rvalue" << std::endl;
    }
};

Widget w;
w.print();          // Lvalue
Widget{}.print();   // Rvalue

std::print 和 std::format

cpp
#include <print>

std::print("Hello, World!\n");
std::print("The answer is {}\n", 42);
std::print("Values: {}, {}, {}\n", 1, 2, 3);

其他改进

cpp
// 改进的 if constexpr
template<typename T>
void process(T value) {
    if constexpr (requires { value.size(); }) {
        std::cout << "Has size: " << value.size() << std::endl;
    } else {
        std::cout << "No size method" << std::endl;
    }
}

版本选择

如何指定 C++ 标准

bash
# GCC/Clang
g++ -std=c++11 file.cpp
g++ -std=c++17 file.cpp
g++ -std=c++20 file.cpp

# MSVC
cl /std:c++17 file.cpp
cl /std:c++20 file.cpp

# CMake
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

特性检查

cpp
#if __cplusplus >= 202002L
    // C++20 或更高
    std::cout << "C++20 or later" << std::endl;
#elif __cplusplus >= 201703L
    // C++17
    std::cout << "C++17" << std::endl;
#elif __cplusplus >= 201402L
    // C++14
    std::cout << "C++14" << std::endl;
#elif __cplusplus >= 201103L
    // C++11
    std::cout << "C++11" << std::endl;
#endif

最佳实践

1. 优先使用现代 C++ 特性

cpp
// 旧方式
int* arr = new int[10];
// ... 使用
delete[] arr;

// 新方式
std::vector<int> arr(10);
// 自动管理

2. 使用智能指针

cpp
// 旧方式
MyClass* obj = new MyClass();
// ... 使用
delete obj;

// 新方式
auto obj = std::make_unique<MyClass>();
// 自动清理

3. 使用范围 for 循环

cpp
// 旧方式
for (size_t i = 0; i < vec.size(); ++i) {
    std::cout << vec[i] << std::endl;
}

// 新方式
for (const auto& item : vec) {
    std::cout << item << std::endl;
}

4. 使用 auto 减少类型冗余

cpp
// 旧方式
std::map<std::string, std::vector<int>>::iterator it = map.begin();

// 新方式
auto it = map.begin();

相关资源

Content is for learning and research only.