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