Skip to content

C++ 现代特性

概述

现代C++(C++11及以后版本)引入了大量新特性,显著改善了语言的表达能力、安全性和性能。本章深入介绍C++11到C++23的重要特性,包括自动类型推导、智能指针、lambda表达式、移动语义、概念等。

🚀 C++11革命性特性

自动类型推导

cpp
#include <iostream>
#include <vector>
#include <map>
#include <memory>

void demonstrateAuto() {
    // ✅ auto关键字
    auto x = 42;                    // int
    auto y = 3.14;                  // double
    auto z = "Hello";               // const char*
    auto str = std::string{"World"}; // std::string
    
    // 复杂类型简化
    std::vector<std::pair<int, std::string>> data;
    
    // C++03方式(冗长)
    for (std::vector<std::pair<int, std::string>>::iterator it = data.begin(); 
         it != data.end(); ++it) {
        // 处理 *it
    }
    
    // C++11方式(简洁)
    for (auto it = data.begin(); it != data.end(); ++it) {
        // 处理 *it
    }
    
    // 范围for循环
    for (const auto& item : data) {
        std::cout << item.first << ": " << item.second << std::endl;
    }
    
    // lambda表达式中的auto
    auto lambda = [](auto x, auto y) { return x + y; };
    
    std::cout << lambda(1, 2) << std::endl;        // int
    std::cout << lambda(1.5, 2.5) << std::endl;   // double
}

// ✅ decltype关键字
template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) {  // C++11返回类型后置
    return t + u;
}

// C++14简化版本
template<typename T, typename U>
auto add_simple(T t, U u) {
    return t + u;
}

// decltype用法
void demonstrateDecltype() {
    int x = 10;
    decltype(x) y = 20;           // y的类型是int
    
    const int& ref = x;
    decltype(ref) z = x;          // z的类型是const int&
    
    // 用于模板编程
    std::vector<int> vec;
    decltype(vec.size()) size = vec.size();  // size_t类型
}

Lambda表达式

cpp
#include <algorithm>
#include <functional>
#include <vector>

class LambdaDemo {
public:
    void demonstrateLambda() {
        std::vector<int> numbers{5, 2, 8, 1, 9};
        
        // ✅ 基本lambda语法
        auto print = [](int x) { std::cout << x << " "; };
        std::for_each(numbers.begin(), numbers.end(), print);
        
        // ✅ 捕获列表
        int threshold = 5;
        
        // 按值捕获
        auto greater_than_threshold = [threshold](int x) { 
            return x > threshold; 
        };
        
        // 按引用捕获
        int count = 0;
        auto counter = [&count](int x) { 
            if (x > 5) ++count; 
        };
        
        std::for_each(numbers.begin(), numbers.end(), counter);
        std::cout << "Count: " << count << std::endl;
        
        // ✅ 捕获所有
        auto lambda_all_by_value = [=]() { 
            return threshold + count;  // 所有外部变量按值捕获
        };
        
        auto lambda_all_by_ref = [&]() { 
            ++count;  // 所有外部变量按引用捕获
            return threshold;
        };
        
        // ✅ 混合捕获
        auto mixed_capture = [&count, threshold](int x) {
            if (x > threshold) ++count;
        };
        
        // ✅ 可变lambda
        auto mutable_lambda = [count](int x) mutable {
            ++count;  // 修改按值捕获的变量副本
            return count + x;
        };
        
        // ✅ 递归lambda
        std::function<int(int)> factorial = [&factorial](int n) -> int {
            return (n <= 1) ? 1 : n * factorial(n - 1);
        };
        
        std::cout << "5! = " << factorial(5) << std::endl;
    }
    
    // ✅ lambda作为函数参数
    template<typename Predicate>
    void processIf(const std::vector<int>& data, Predicate pred) {
        for (const auto& item : data) {
            if (pred(item)) {
                std::cout << item << " passed test" << std::endl;
            }
        }
    }
    
    void useLambdaAsParameter() {
        std::vector<int> data{1, 2, 3, 4, 5};
        
        processIf(data, [](int x) { return x % 2 == 0; });  // 偶数
        processIf(data, [](int x) { return x > 3; });       // 大于3
    }
};

智能指针

cpp
#include <memory>
#include <iostream>

class Resource {
public:
    Resource(int id) : id_(id) {
        std::cout << "Resource " << id_ << " created" << std::endl;
    }
    
    ~Resource() {
        std::cout << "Resource " << id_ << " destroyed" << std::endl;
    }
    
    void use() {
        std::cout << "Using resource " << id_ << std::endl;
    }
    
    int getId() const { return id_; }
    
private:
    int id_;
};

void demonstrateSmartPointers() {
    // ✅ unique_ptr - 独占所有权
    std::unique_ptr<Resource> unique_res = std::make_unique<Resource>(1);
    unique_res->use();
    
    // 转移所有权
    std::unique_ptr<Resource> moved_res = std::move(unique_res);
    // unique_res现在为nullptr
    
    if (moved_res) {
        moved_res->use();
    }
    
    // ✅ shared_ptr - 共享所有权
    std::shared_ptr<Resource> shared_res1 = std::make_shared<Resource>(2);
    std::cout << "Reference count: " << shared_res1.use_count() << std::endl;
    
    {
        std::shared_ptr<Resource> shared_res2 = shared_res1;
        std::cout << "Reference count: " << shared_res1.use_count() << std::endl;
        shared_res2->use();
    }  // shared_res2析构,引用计数减1
    
    std::cout << "Reference count: " << shared_res1.use_count() << std::endl;
    
    // ✅ weak_ptr - 避免循环引用
    std::weak_ptr<Resource> weak_res = shared_res1;
    
    if (auto locked = weak_res.lock()) {  // 尝试获取shared_ptr
        locked->use();
        std::cout << "Resource is still alive" << std::endl;
    }
    
    shared_res1.reset();  // 释放资源
    
    if (weak_res.expired()) {
        std::cout << "Resource has been destroyed" << std::endl;
    }
}

// ✅ 自定义删除器
void demonstrateCustomDeleter() {
    auto custom_deleter = [](Resource* res) {
        std::cout << "Custom deleter called for resource " << res->getId() << std::endl;
        delete res;
    };
    
    std::unique_ptr<Resource, decltype(custom_deleter)> res(
        new Resource(99), custom_deleter);
    
    // C数组的智能指针
    std::unique_ptr<int[]> arr = std::make_unique<int[]>(10);
    for (int i = 0; i < 10; ++i) {
        arr[i] = i * i;
    }
}

移动语义

cpp
#include <vector>
#include <string>
#include <utility>

class MoveableResource {
private:
    std::vector<int> data_;
    std::string name_;
    
public:
    // 构造函数
    MoveableResource(const std::string& name, size_t size) 
        : name_(name), data_(size, 0) {
        std::cout << "Constructor: " << name_ << std::endl;
    }
    
    // ✅ 拷贝构造函数
    MoveableResource(const MoveableResource& other) 
        : name_(other.name_), data_(other.data_) {
        std::cout << "Copy constructor: " << name_ << std::endl;
    }
    
    // ✅ 移动构造函数
    MoveableResource(MoveableResource&& other) noexcept
        : name_(std::move(other.name_)), data_(std::move(other.data_)) {
        std::cout << "Move constructor: " << name_ << std::endl;
    }
    
    // ✅ 拷贝赋值运算符
    MoveableResource& operator=(const MoveableResource& other) {
        if (this != &other) {
            name_ = other.name_;
            data_ = other.data_;
            std::cout << "Copy assignment: " << name_ << std::endl;
        }
        return *this;
    }
    
    // ✅ 移动赋值运算符
    MoveableResource& operator=(MoveableResource&& other) noexcept {
        if (this != &other) {
            name_ = std::move(other.name_);
            data_ = std::move(other.data_);
            std::cout << "Move assignment: " << name_ << std::endl;
        }
        return *this;
    }
    
    ~MoveableResource() {
        std::cout << "Destructor: " << name_ << std::endl;
    }
    
    const std::string& getName() const { return name_; }
    size_t size() const { return data_.size(); }
};

// ✅ 完美转发
template<typename T>
void wrapper(T&& arg) {
    process(std::forward<T>(arg));  // 完美转发
}

void process(const MoveableResource& res) {
    std::cout << "Processing lvalue: " << res.getName() << std::endl;
}

void process(MoveableResource&& res) {
    std::cout << "Processing rvalue: " << res.getName() << std::endl;
}

void demonstrateMoveSematics() {
    // 拷贝
    MoveableResource res1("Resource1", 1000);
    MoveableResource res2 = res1;  // 拷贝构造
    
    // 移动
    MoveableResource res3 = std::move(res1);  // 移动构造
    
    // res1现在处于有效但未指定状态
    std::cout << "res1 name after move: '" << res1.getName() << "'" << std::endl;
    
    // 函数返回值优化(RVO)
    auto createResource = []() {
        return MoveableResource("TempResource", 500);
    };
    
    MoveableResource res4 = createResource();  // 可能触发移动或RVO
    
    // 完美转发测试
    MoveableResource res5("ForwardTest", 100);
    wrapper(res5);                             // 左值引用
    wrapper(std::move(res5));                  // 右值引用
    wrapper(MoveableResource("Temp", 50));     // 临时对象
}

🔧 C++14增强特性

auto和lambda改进

cpp
#include <iostream>
#include <vector>
#include <algorithm>

void demonstrateCpp14Features() {
    // ✅ auto返回类型推导
    auto multiply = [](auto x, auto y) {
        return x * y;  // 返回类型自动推导
    };
    
    std::cout << multiply(3, 4) << std::endl;      // int
    std::cout << multiply(2.5, 3.0) << std::endl; // double
    
    // ✅ 泛型lambda
    auto process = [](auto&& container) {
        using T = std::decay_t<decltype(container)>;
        std::cout << "Processing container of size: " << container.size() << std::endl;
        
        std::for_each(container.begin(), container.end(), [](const auto& item) {
            std::cout << item << " ";
        });
        std::cout << std::endl;
    };
    
    std::vector<int> numbers{1, 2, 3, 4, 5};
    std::vector<std::string> words{"hello", "world"};
    
    process(numbers);
    process(words);
    
    // ✅ 初始化捕获
    auto counter = [count = 0](int increment) mutable {
        count += increment;
        return count;
    };
    
    std::cout << counter(5) << std::endl;   // 5
    std::cout << counter(3) << std::endl;   // 8
    
    // ✅ 移动捕获
    auto data = std::make_unique<std::vector<int>>(10, 42);
    auto lambda_with_move = [captured_data = std::move(data)](int index) {
        if (index < captured_data->size()) {
            return (*captured_data)[index];
        }
        return -1;
    };
    
    std::cout << lambda_with_move(5) << std::endl;  // 42
}

// ✅ 变量模板(C++14)
template<typename T>
constexpr T pi = T(3.1415926535897932385);

void demonstrateVariableTemplates() {
    std::cout << "pi<float>: " << pi<float> << std::endl;
    std::cout << "pi<double>: " << pi<double> << std::endl;
    std::cout << "pi<long double>: " << pi<long double> << std::endl;
}

🎯 C++17实用特性

结构化绑定

cpp
#include <tuple>
#include <map>
#include <string>

void demonstrateStructuredBindings() {
    // ✅ tuple解包
    auto getData() {
        return std::make_tuple(42, "Hello", 3.14);
    }
    
    auto [id, message, value] = getData();
    std::cout << id << ", " << message << ", " << value << std::endl;
    
    // ✅ pair解包
    std::map<std::string, int> scores{{"Alice", 95}, {"Bob", 87}};
    
    for (const auto& [name, score] : scores) {
        std::cout << name << ": " << score << std::endl;
    }
    
    // ✅ 数组解包
    int arr[] = {1, 2, 3};
    auto [a, b, c] = arr;
    std::cout << a << ", " << b << ", " << c << std::endl;
    
    // ✅ 自定义类型
    struct Point {
        int x, y;
    };
    
    Point p{10, 20};
    auto [x, y] = p;
    std::cout << "Point: (" << x << ", " << y << ")" << std::endl;
}

// ✅ if constexpr
template<typename T>
void processValue(T value) {
    if constexpr (std::is_integral_v<T>) {
        std::cout << "Processing integer: " << value << std::endl;
    } else if constexpr (std::is_floating_point_v<T>) {
        std::cout << "Processing floating point: " << value << std::endl;
    } else if constexpr (std::is_same_v<T, std::string>) {
        std::cout << "Processing string: " << value << std::endl;
    } else {
        std::cout << "Processing unknown type" << std::endl;
    }
}

// ✅ std::optional
#include <optional>

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

void demonstrateOptional() {
    auto result = divide(10, 2);
    if (result) {
        std::cout << "Result: " << *result << std::endl;
    }
    
    auto invalid = divide(10, 0);
    if (!invalid) {
        std::cout << "Division by zero!" << std::endl;
    }
    
    // 使用value_or提供默认值
    std::cout << "Safe result: " << invalid.value_or(-1) << std::endl;
}

// ✅ std::variant
#include <variant>

void demonstrateVariant() {
    std::variant<int, std::string, double> data;
    
    data = 42;
    std::cout << "Holds int: " << std::get<int>(data) << std::endl;
    
    data = std::string("Hello");
    std::cout << "Holds string: " << std::get<std::string>(data) << std::endl;
    
    data = 3.14;
    std::cout << "Holds double: " << std::get<double>(data) << std::endl;
    
    // 访问者模式
    std::visit([](const auto& value) {
        std::cout << "Visiting: " << value << std::endl;
    }, data);
    
    // 类型安全访问
    if (std::holds_alternative<double>(data)) {
        std::cout << "Currently holds double" << std::endl;
    }
}

🔥 C++20革命性特性

概念 (Concepts)

cpp
#include <concepts>
#include <iostream>
#include <vector>

// ✅ 标准概念
template<std::integral T>
void processInteger(T value) {
    std::cout << "Processing integer: " << value << std::endl;
}

template<std::floating_point T>
void processFloat(T value) {
    std::cout << "Processing float: " << value << std::endl;
}

// ✅ 自定义概念
template<typename T>
concept Printable = requires(T t) {
    std::cout << t;
};

template<typename T>
concept Container = requires(T t) {
    typename T::value_type;
    typename T::iterator;
    t.begin();
    t.end();
    t.size();
};

template<Container T>
void printContainer(const T& container) {
    std::cout << "Container size: " << container.size() << std::endl;
    for (const auto& item : container) {
        std::cout << item << " ";
    }
    std::cout << std::endl;
}

// ✅ 复杂概念
template<typename T>
concept Comparable = requires(T a, T b) {
    { a == b } -> std::convertible_to<bool>;
    { a != b } -> std::convertible_to<bool>;
    { a < b } -> std::convertible_to<bool>;
};

template<Comparable T>
T findMax(const std::vector<T>& data) {
    if (data.empty()) {
        throw std::invalid_argument("Empty container");
    }
    
    T max_val = data[0];
    for (const auto& item : data) {
        if (item > max_val) {
            max_val = item;
        }
    }
    return max_val;
}

void demonstrateConcepts() {
    processInteger(42);
    processFloat(3.14);
    
    std::vector<int> numbers{1, 2, 3, 4, 5};
    printContainer(numbers);
    
    auto max_num = findMax(numbers);
    std::cout << "Max: " << max_num << std::endl;
}

协程 (Coroutines)

cpp
#include <coroutine>
#include <iostream>
#include <exception>

// ✅ 简单生成器
template<typename T>
struct Generator {
    struct promise_type {
        T current_value;
        
        Generator get_return_object() {
            return Generator{std::coroutine_handle<promise_type>::from_promise(*this)};
        }
        
        std::suspend_always initial_suspend() { return {}; }
        std::suspend_always final_suspend() noexcept { return {}; }
        
        std::suspend_always yield_value(T value) {
            current_value = value;
            return {};
        }
        
        void return_void() {}
        void unhandled_exception() {}
    };
    
    std::coroutine_handle<promise_type> coro;
    
    Generator(std::coroutine_handle<promise_type> h) : coro(h) {}
    
    ~Generator() {
        if (coro) {
            coro.destroy();
        }
    }
    
    // 迭代器接口
    struct iterator {
        std::coroutine_handle<promise_type> coro;
        bool done;
        
        iterator(std::coroutine_handle<promise_type> h, bool is_done) 
            : coro(h), done(is_done) {}
        
        T operator*() const { return coro.promise().current_value; }
        
        iterator& operator++() {
            coro.resume();
            done = coro.done();
            return *this;
        }
        
        bool operator==(const iterator& other) const {
            return done == other.done;
        }
    };
    
    iterator begin() {
        if (coro) {
            coro.resume();
            return iterator{coro, coro.done()};
        }
        return iterator{nullptr, true};
    }
    
    iterator end() {
        return iterator{nullptr, true};
    }
};

// ✅ 斐波那契数列生成器
Generator<int> fibonacci(int count) {
    int a = 0, b = 1;
    for (int i = 0; i < count; ++i) {
        co_yield a;
        auto temp = a + b;
        a = b;
        b = temp;
    }
}

void demonstrateCoroutines() {
    std::cout << "Fibonacci sequence:" << std::endl;
    for (int value : fibonacci(10)) {
        std::cout << value << " ";
    }
    std::cout << std::endl;
}

模块 (Modules)

cpp
// ✅ 模块定义文件 math_module.cpp
/*
export module math_utils;

export namespace math {
    int add(int a, int b) {
        return a + b;
    }
    
    int multiply(int a, int b) {
        return a * b;
    }
    
    template<typename T>
    T power(T base, int exponent) {
        T result = 1;
        for (int i = 0; i < exponent; ++i) {
            result *= base;
        }
        return result;
    }
}

// 内部实现(不导出)
namespace {
    int internal_helper(int x) {
        return x * 2;
    }
}
*/

// ✅ 使用模块
/*
import math_utils;
#include <iostream>

int main() {
    std::cout << math::add(2, 3) << std::endl;
    std::cout << math::multiply(4, 5) << std::endl;
    std::cout << math::power(2, 8) << std::endl;
    
    return 0;
}
*/

🌟 C++23新特性预览

改进的范围算法

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

void demonstrateRanges() {
    std::vector<int> numbers{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    
    // ✅ 范围视图组合
    auto even_squares = numbers 
        | std::views::filter([](int n) { return n % 2 == 0; })
        | std::views::transform([](int n) { return n * n; });
    
    std::cout << "Even squares: ";
    for (int value : even_squares) {
        std::cout << value << " ";
    }
    std::cout << std::endl;
    
    // ✅ 范围算法
    std::vector<int> sorted_data = numbers;
    std::ranges::sort(sorted_data, std::greater{});
    
    std::cout << "Sorted (descending): ";
    std::ranges::copy(sorted_data, std::ostream_iterator<int>(std::cout, " "));
    std::cout << std::endl;
    
    // ✅ 投影
    std::vector<std::string> words{"hello", "world", "cpp", "modern"};
    
    // 按长度排序
    std::ranges::sort(words, {}, &std::string::size);
    
    std::cout << "Sorted by length: ";
    for (const auto& word : words) {
        std::cout << word << " ";
    }
    std::cout << std::endl;
}

// ✅ std::expected (C++23)
#include <expected>

std::expected<int, std::string> divide_safe(int a, int b) {
    if (b == 0) {
        return std::unexpected{"Division by zero"};
    }
    return a / b;
}

void demonstrateExpected() {
    auto result1 = divide_safe(10, 2);
    if (result1) {
        std::cout << "Result: " << *result1 << std::endl;
    }
    
    auto result2 = divide_safe(10, 0);
    if (!result2) {
        std::cout << "Error: " << result2.error() << std::endl;
    }
}

总结

C++现代特性时间线

版本关键特性影响
C++11auto, lambda, 智能指针, 移动语义革命性变化
C++14泛型lambda, auto返回类型增量改进
C++17结构化绑定, if constexpr, optional实用性提升
C++20概念, 协程, 模块, 范围下一代特性
C++23expected, 改进的范围持续演进

采用建议

  • 立即使用: auto, lambda, 智能指针, 范围for
  • 积极采用: 结构化绑定, optional, variant
  • 谨慎尝试: 协程, 模块(工具链支持)
  • 关注发展: 概念, 范围算法

学习路径

  1. 基础: auto, lambda, 智能指针
  2. 进阶: 移动语义, 完美转发
  3. 现代: 概念, 协程, 模块
  4. 未来: 持续关注标准发展

最佳实践

  • 渐进式采用: 不要一次性使用所有新特性
  • 团队一致: 建立团队的现代C++使用规范
  • 工具支持: 确保编译器和工具链支持
  • 性能意识: 新特性不等于更好的性能
  • 可读性优先: 代码清晰比使用新特性更重要

现代C++特性极大地改善了语言的表达能力和安全性,但需要循序渐进地学习和采用。关键是理解每个特性的适用场景,在合适的时候使用合适的特性。

本站内容仅供学习和研究使用。