C++进阶知识大全(一)

简介: 教程来源 https://app-ad0bpnnq0o3l.appmiaoda.com 本文系统梳理C++进阶核心:RAII与智能指针、移动语义、模板元编程、完美转发、并发编程、STL深度剖析及性能优化,配以精讲代码示例,助你突破语法瓶颈,掌握资源管理、零开销抽象与高效并发等关键能力,迈向资深C++开发者。

当你已经掌握了C++的基础语法,能够编写简单的面向对象程序时,真正的挑战才刚刚开始。C++进阶开发要求你深入理解内存模型、掌握模板元编程、精通RAII与智能指针、熟悉移动语义、掌握并发编程、理解性能优化。本文将系统梳理C++进阶开发的核心知识体系,涵盖RAII与智能指针、移动语义、模板进阶、lambda表达式、并发编程、STL深度剖析、异常安全、性能优化等关键领域,助你突破瓶颈,成为一名真正高效的C++开发者。
a7b1db4f-eb2c-4b46-8883-ad94ea9e956d.png

一、RAII与资源管理

1.1 RAII原则详解
RAII(Resource Acquisition Is Initialization)是C++中最核心的编程范式,它将资源的生命周期与对象的生命周期绑定。

#include <iostream>
#include <fstream>
#include <mutex>
#include <thread>
#include <stdexcept>

// ========== 传统资源管理(容易出错) ==========
void traditional_resource_management() {
    int* p = new int(10);
    // ... 可能发生异常,导致内存泄漏
    delete p;  // 如果发生异常,这行不会执行
}

// ========== RAII资源管理 ==========
class FileHandle {
private:
    FILE* file;

public:
    FileHandle(const char* filename, const char* mode) {
        file = fopen(filename, mode);
        if (!file) {
            throw std::runtime_error("无法打开文件");
        }
        std::cout << "文件已打开" << std::endl;
    }

    ~FileHandle() {
        if (file) {
            fclose(file);
            std::cout << "文件已关闭" << std::endl;
        }
    }

    // 禁止拷贝
    FileHandle(const FileHandle&) = delete;
    FileHandle& operator=(const FileHandle&) = delete;

    // 移动语义
    FileHandle(FileHandle&& other) noexcept : file(other.file) {
        other.file = nullptr;
    }

    FileHandle& operator=(FileHandle&& other) noexcept {
        if (this != &other) {
            if (file) fclose(file);
            file = other.file;
            other.file = nullptr;
        }
        return *this;
    }

    void write(const std::string& data) {
        if (file) {
            fprintf(file, "%s\n", data.c_str());
        }
    }
};

// ========== 互斥锁的RAII封装 ==========
class MutexGuard {
private:
    std::mutex& mtx;

public:
    explicit MutexGuard(std::mutex& m) : mtx(m) {
        mtx.lock();
        std::cout << "互斥锁已锁定" << std::endl;
    }

    ~MutexGuard() {
        mtx.unlock();
        std::cout << "互斥锁已解锁" << std::endl;
    }

    MutexGuard(const MutexGuard&) = delete;
    MutexGuard& operator=(const MutexGuard&) = delete;
};

void raii_demo() {
    try {
        FileHandle fh("test.txt", "w");
        fh.write("Hello, RAII!");
        // 无论是否发生异常,文件都会在fh析构时关闭
        throw std::runtime_error("模拟异常");
    } catch (const std::exception& e) {
        std::cout << "异常:" << e.what() << std::endl;
    }

    std::mutex mtx;
    {
        MutexGuard guard(mtx);
        // 临界区代码
    }  // 离开作用域自动解锁
}

1.2 智能指针深度剖析

#include <memory>
#include <iostream>
#include <vector>

// ========== std::unique_ptr ==========
class Widget {
public:
    Widget() { std::cout << "Widget构造" << std::endl; }
    ~Widget() { std::cout << "Widget析构" << std::endl; }
    void process() { std::cout << "处理中..." << std::endl; }
};

void unique_ptr_demo() {
    // 创建unique_ptr
    auto p1 = std::make_unique<Widget>();
    p1->process();

    // 转移所有权
    auto p2 = std::move(p1);
    if (!p1) std::cout << "p1为空" << std::endl;
    p2->process();

    // 自定义删除器
    auto custom_deleter = [](Widget* p) {
        std::cout << "自定义删除器" << std::endl;
        delete p;
    };
    std::unique_ptr<Widget, decltype(custom_deleter)> p3(new Widget(), custom_deleter);

    // 数组版本
    auto arr = std::make_unique<int[]>(10);
    for (int i = 0; i < 10; i++) {
        arr[i] = i;
    }
}

// ========== std::shared_ptr与引用计数 ==========
class Node {
public:
    int value;
    std::shared_ptr<Node> next;
    std::weak_ptr<Node> prev;  // 使用weak_ptr打破循环引用

    Node(int v) : value(v) {
        std::cout << "Node构造: " << value << std::endl;
    }
    ~Node() {
        std::cout << "Node析构: " << value << std::endl;
    }
};

void shared_ptr_demo() {
    // 创建shared_ptr
    auto sp1 = std::make_shared<int>(42);
    std::cout << "引用计数: " << sp1.use_count() << std::endl;

    {
        auto sp2 = sp1;  // 共享所有权
        std::cout << "引用计数: " << sp1.use_count() << std::endl;
    }
    std::cout << "引用计数: " << sp1.use_count() << std::endl;

    // 循环引用问题(使用weak_ptr解决)
    auto node1 = std::make_shared<Node>(1);
    auto node2 = std::make_shared<Node>(2);

    node1->next = node2;
    node2->prev = node1;  // weak_ptr不会增加引用计数

    // 使用weak_ptr
    if (auto locked = node2->prev.lock()) {
        std::cout << "prev value: " << locked->value << std::endl;
    }
}

// ========== std::weak_ptr ==========
void weak_ptr_demo() {
    std::shared_ptr<int> sp = std::make_shared<int>(100);
    std::weak_ptr<int> wp = sp;

    // 检查shared_ptr是否有效
    if (auto locked = wp.lock()) {
        std::cout << "值: " << *locked << std::endl;
    } else {
        std::cout << "shared_ptr已失效" << std::endl;
    }

    sp.reset();  // 释放shared_ptr

    if (wp.expired()) {
        std::cout << "weak_ptr已过期" << std::endl;
    }
}

// ========== 自定义智能指针 ==========
template<typename T>
class MySmartPtr {
private:
    T* ptr;

public:
    explicit MySmartPtr(T* p = nullptr) : ptr(p) {}

    ~MySmartPtr() {
        delete ptr;
    }

    // 禁止拷贝
    MySmartPtr(const MySmartPtr&) = delete;
    MySmartPtr& operator=(const MySmartPtr&) = delete;

    // 移动语义
    MySmartPtr(MySmartPtr&& other) noexcept : ptr(other.ptr) {
        other.ptr = nullptr;
    }

    MySmartPtr& operator=(MySmartPtr&& other) noexcept {
        if (this != &other) {
            delete ptr;
            ptr = other.ptr;
            other.ptr = nullptr;
        }
        return *this;
    }

    T& operator*() const { return *ptr; }
    T* operator->() const { return ptr; }
    explicit operator bool() const { return ptr != nullptr; }
};

void custom_smart_ptr_demo() {
    MySmartPtr<Widget> ptr(new Widget());
    ptr->process();
    (*ptr).process();
}

二、移动语义与完美转发

2.1 左值、右值与移动语义

#include <iostream>
#include <vector>
#include <string>
#include <utility>

// ========== 左值与右值 ==========
void lvalue_rvalue_demo() {
    int x = 10;      // x是左值
    int y = x + 5;   // x+5是右值

    // 左值引用
    int& lref = x;   // 左值引用绑定到左值

    // 右值引用(C++11)
    int&& rref = 20; // 右值引用绑定到右值

    // std::move将左值转换为右值引用
    int&& rref2 = std::move(x);
}

// ========== 移动构造函数与移动赋值 ==========
class BigData {
private:
    int* data;
    size_t size;

public:
    // 构造函数
    BigData(size_t n) : size(n), data(new int[n]) {
        std::cout << "构造函数" << std::endl;
    }

    // 析构函数
    ~BigData() {
        delete[] data;
        std::cout << "析构函数" << std::endl;
    }

    // 拷贝构造函数(深拷贝)
    BigData(const BigData& other) : size(other.size), data(new int[other.size]) {
        std::copy(other.data, other.data + size, data);
        std::cout << "拷贝构造" << std::endl;
    }

    // 移动构造函数(浅拷贝,转移所有权)
    BigData(BigData&& other) noexcept : data(other.data), size(other.size) {
        other.data = nullptr;
        other.size = 0;
        std::cout << "移动构造" << std::endl;
    }

    // 拷贝赋值运算符
    BigData& operator=(const BigData& other) {
        if (this != &other) {
            delete[] data;
            size = other.size;
            data = new int[size];
            std::copy(other.data, other.data + size, data);
            std::cout << "拷贝赋值" << std::endl;
        }
        return *this;
    }

    // 移动赋值运算符
    BigData& operator=(BigData&& other) noexcept {
        if (this != &other) {
            delete[] data;
            data = other.data;
            size = other.size;
            other.data = nullptr;
            other.size = 0;
            std::cout << "移动赋值" << std::endl;
        }
        return *this;
    }

    size_t getSize() const { return size; }
};

BigData createBigData() {
    BigData temp(1000);
    return temp;  // 返回值优化(RVO)或移动语义
}

void move_semantics_demo() {
    BigData bd1(100);
    BigData bd2 = std::move(bd1);  // 移动构造
    // bd1现在处于“有效但未指定”状态

    BigData bd3(200);
    bd3 = std::move(bd2);          // 移动赋值

    BigData bd4 = createBigData();  // RVO或移动
}

// ========== std::move与std::forward ==========
void process(const std::string& s) {
    std::cout << "左值引用: " << s << std::endl;
}

void process(std::string&& s) {
    std::cout << "右值引用: " << s << std::endl;
}

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

void move_forward_demo() {
    std::string s = "hello";

    forward_example(s);            // 传递左值,调用process(const std::string&)
    forward_example(std::move(s)); // 传递右值,调用process(std::string&&)
    forward_example("world");      // 传递右值
}

2.2 引用折叠与完美转发

#include <iostream>
#include <utility>

// ========== 引用折叠规则 ==========
/*
 * 引用折叠规则:
 * T& &   -> T&
 * T& &&  -> T&
 * T&& &  -> T&
 * T&& && -> T&&
 */

// ========== 完美转发实现 ==========
template<typename T>
void wrapper(T&& arg) {
    // 使用std::forward保持参数的左右值属性
    foo(std::forward<T>(arg));
}

void foo(int& x) {
    std::cout << "左值引用: " << x << std::endl;
}

void foo(int&& x) {
    std::cout << "右值引用: " << x << std::endl;
}

void perfect_forwarding_demo() {
    int a = 10;
    wrapper(a);           // 传递左值
    wrapper(20);          // 传递右值
    wrapper(std::move(a)); // 传递右值
}

// ========== 工厂函数中的完美转发 ==========
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

class Person {
public:
    std::string name;
    int age;

    Person(const std::string& n, int a) : name(n), age(a) {
        std::cout << "拷贝构造Person: " << name << std::endl;
    }

    Person(std::string&& n, int a) : name(std::move(n)), age(a) {
        std::cout << "移动构造Person: " << name << std::endl;
    }
};

void factory_demo() {
    std::string name = "张三";
    auto p1 = make_unique<Person>(name, 25);      // 拷贝
    auto p2 = make_unique<Person>(std::move(name), 30); // 移动
}

三、模板进阶

3.1 函数模板与类模板

#include <iostream>
#include <vector>
#include <type_traits>

// ========== 函数模板 ==========
template<typename T>
T max(T a, T b) {
    return (a > b) ? a : b;
}

// 特化
template<>
const char* max<const char*>(const char* a, const char* b) {
    return (strcmp(a, b) > 0) ? a : b;
}

// ========== 类模板 ==========
template<typename T, size_t N>
class Array {
private:
    T data[N];

public:
    size_t size() const { return N; }

    T& operator[](size_t index) {
        return data[index];
    }

    const T& operator[](size_t index) const {
        return data[index];
    }

    T* begin() { return data; }
    T* end() { return data + N; }
};

// ========== 类模板特化 ==========
template<typename T>
class Stack {
public:
    void push(const T& value) { /* ... */ }
    T pop() { /* ... */ }
};

// 完全特化
template<>
class Stack<bool> {
public:
    void push(bool value) { /* 位压缩存储 */ }
    bool pop() { /* ... */ }
};

// ========== 偏特化 ==========
template<typename T, typename U>
class Pair {
public:
    T first;
    U second;
};

// 偏特化:当两个类型相同时
template<typename T>
class Pair<T, T> {
public:
    T first;
    T second;
    T sum() const { return first + second; }
};

// 偏特化:当第二个类型为void时
template<typename T>
class Pair<T, void> {
public:
    T first;
};

// ========== 可变参数模板 ==========
// 基础情况
void print() {}

// 递归展开
template<typename T, typename... Args>
void print(T first, Args... args) {
    std::cout << first << " ";
    print(args...);
}

// 折叠表达式(C++17)
template<typename... Args>
auto sum(Args... args) {
    return (args + ...);  // 右折叠
    // 或 (... + args);   // 左折叠
}

// 逗号折叠
template<typename... Args>
void print_all(Args... args) {
    (std::cout << ... << args) << std::endl;  // C++17
    // 或 (std::cout << args << " ", ...);
}

void variadic_template_demo() {
    print(1, 2.5, "hello", 'A');
    std::cout << std::endl;

    std::cout << "sum: " << sum(1, 2, 3, 4, 5) << std::endl;

    print_all(1, " ", 2.5, " ", "world");
}

3.2 模板元编程

#include <iostream>
#include <type_traits>

// ========== 编译期计算 ==========
// 阶乘(递归模板)
template<int N>
struct Factorial {
    static constexpr int value = N * Factorial<N - 1>::value;
};

template<>
struct Factorial<0> {
    static constexpr int value = 1;
};

// 斐波那契数列
template<int N>
struct Fibonacci {
    static constexpr int value = Fibonacci<N - 1>::value + Fibonacci<N - 2>::value;
};

template<>
struct Fibonacci<0> {
    static constexpr int value = 0;
};

template<>
struct Fibonacci<1> {
    static constexpr int value = 1;
};

// ========== 类型萃取 ==========
// 判断是否为指针
template<typename T>
struct IsPointer {
    static constexpr bool value = false;
};

template<typename T>
struct IsPointer<T*> {
    static constexpr bool value = true;
};

// 移除引用
template<typename T>
struct RemoveReference {
    using type = T;
};

template<typename T>
struct RemoveReference<T&> {
    using type = T;
};

template<typename T>
struct RemoveReference<T&&> {
    using type = T;
};

// 添加const
template<typename T>
struct AddConst {
    using type = const T;
};

// 类型选择(类似三元运算符)
template<bool Cond, typename TrueType, typename FalseType>
struct Conditional {
    using type = TrueType;
};

template<typename TrueType, typename FalseType>
struct Conditional<false, TrueType, FalseType> {
    using type = FalseType;
};

// ========== SFINAE ==========
// Substitution Failure Is Not An Error
template<typename T>
typename T::value_type sum(const T& container) {
    typename T::value_type total = 0;
    for (const auto& v : container) {
        total += v;
    }
    return total;
}

// 使用enable_if
template<typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type
half(T x) {
    return x / 2;
}

template<typename T>
typename std::enable_if<!std::is_integral<T>::value, T>::type
half(T x) {
    return x / 2.0;
}

// ========== constexpr函数 ==========
constexpr int factorial(int n) {
    return (n <= 1) ? 1 : n * factorial(n - 1);
}

constexpr int fibonacci(int n) {
    return (n <= 1) ? n : fibonacci(n - 1) + fibonacci(n - 2);
}

// constexpr if(C++17)
template<typename T>
auto get_value(T t) {
    if constexpr (std::is_pointer_v<T>) {
        return *t;
    } else {
        return t;
    }
}

void template_metaprogramming_demo() {
    // 编译期计算
    std::cout << "5! = " << Factorial<5>::value << std::endl;
    std::cout << "Fibonacci(10) = " << Fibonacci<10>::value << std::endl;

    // 类型萃取
    std::cout << std::boolalpha;
    std::cout << "int是指针?" << IsPointer<int>::value << std::endl;
    std::cout << "int*是指针?" << IsPointer<int*>::value << std::endl;

    // constexpr
    constexpr int fact5 = factorial(5);
    std::cout << "constexpr 5! = " << fact5 << std::endl;

    int x = 10;
    std::cout << "half(10) = " << half(x) << std::endl;
    double d = 10.5;
    std::cout << "half(10.5) = " << half(d) << std::endl;
}

来源:
https://app-ad0bpnnq0o3l.appmiaoda.com

相关文章
|
编解码 物联网 Android开发
|
16天前
|
JavaScript 前端开发 API
VUE前端初级新手知识大全(一)
教程来源 https://app-a6nw7st4g741.appmiaoda.com/ Vue.js是轻量、易上手的渐进式前端框架,专注视图层,支持声明式编程与MVVM模式。本文系统讲解入门知识:从CDN/CLI环境搭建、核心语法(插值、指令、ref/reactive)、响应式原理,到计算属性与侦听器,助你快速构建首个Vue应用。
|
4月前
|
安全 Java API
Java日期处理完全指南(新手也能轻松掌握的Java时间格式化与日期API教程)
教程来源https://www.vpshk.cn/本文介绍Java 8引入的java.time包,详解LocalDateTime、LocalDate等类的使用,涵盖获取当前时间、格式化、解析字符串及日期运算,助你轻松掌握现代Java日期处理方法,适合初学者快速上手。
|
10天前
|
XML Java Maven
Spring Boot学习知识点大全(一)
教程来源 https://app-a87ujc988w01.appmiaoda.com/ Spring Boot 是 Spring 家族中革命性框架,秉持“约定优于配置”理念,通过自动配置、起步依赖、嵌入式服务器等特性,大幅简化企业级 Java 应用开发。本文系统梳理其核心概念、注解、多环境配置与最佳实践,助初学者快速入门,为进阶开发者提供深度参考。
|
6月前
|
IDE Java 编译器
java编程最基础学习
Java入门需掌握:环境搭建、基础语法、面向对象、数组集合与异常处理。通过实践编写简单程序,逐步深入学习,打牢编程基础。
358 1
|
安全 编译器 程序员
C++ noexcept 关键字的关键作用
`noexcept` 关键字在 C++ 中扮演着重要角色,通过正确使用 `noexcept`,可以提升程序的性能、增强代码的可读性和安全性,并且有助于编译器进行优化。在编写 C++ 代码时,应仔细考虑每个函数是否应该声明为 `noexcept`,以充分利用这一特性带来的优势。通过本文的介绍,希望开发者能够更好地理解和应用 `noexcept` 关键字,从而编写出更加高效、健壮的 C++ 程序。
453 8
|
安全 编译器 C语言
MISRA C++ 、Google C++ 、AUTOSAR Adaptive Platform编码 C++ 规范总结
MISRA C++ 、Google C++ 、AUTOSAR Adaptive Platform编码 C++ 规范总结
607 1
|
机器学习/深度学习 数据采集 自然语言处理
自然语言处理中的文本分类技术深度解析
【7月更文挑战第31天】文本分类作为自然语言处理领域的重要技术之一,正不断推动着智能信息处理的发展。随着深度学习技术的不断成熟和计算资源的日益丰富,我们有理由相信,未来的文本分类技术将更加智能化、高效化、普适化,为人类社会带来更加便捷、精准的信息服务。
|
弹性计算 运维 负载均衡
阿里云轻量应用服务器产品简介、收费标准与活动价格、搭建个人博客教程参考
阿里云轻量应用服务器是深受个人和普通企业用户亲耐的一款轻量级云服务器产品,提供精品应用一键部署,支持一站式的域名、网站、安全、运维、应用管理等服务,极大优化搭建简单应用的体验,降低了入门级用户使用云计算产品的门槛。本文来介绍全方位介绍一下阿里云轻量应用服务器的产品知识,以及最新的收费标准与活动价格情况,另外再奉上使用轻量应用服务器搭建个人博客的建站教程,以供参考。
阿里云轻量应用服务器产品简介、收费标准与活动价格、搭建个人博客教程参考

热门文章

最新文章