1. C++语言概述与核心特性
C++作为一门经典的编程语言,自1983年由Bjarne Stroustrup在贝尔实验室开发以来,已经发展成为系统级编程的基石。它完美继承了C语言的高效特性,同时引入了面向对象编程范式,使其在性能与抽象能力之间取得了绝佳平衡。
提示:现代C++标准(C++11/14/17/20)引入了大量新特性,建议新手从C++11开始学习,避免接触过于陈旧的编程风格。
C++的核心优势主要体现在三个方面:首先是直接内存操作能力,通过指针和引用可以精确控制每一个字节;其次是零成本抽象原则,高级特性如模板、虚函数等不会带来运行时开销;最后是跨平台兼容性,同一套代码经过不同编译器处理即可在多种系统上运行。
在实际工业应用中,C++的身影无处不在:
- 操作系统内核(Linux/Windows/macOS)
- 游戏引擎(Unreal Engine)
- 高频交易系统
- 嵌入式设备固件
- 浏览器渲染引擎(Chrome V8)
- 数据库管理系统(MySQL/MongoDB)
1.1 编译型语言的执行流程
与Python等解释型语言不同,C++代码需要经过完整的编译-链接过程才能执行。以最简单的Hello World程序为例:
cpp复制#include <iostream>
using namespace std;
int main() {
cout << "Hello World!" << endl;
return 0;
}
这个程序会经历四个关键处理阶段:
- 预处理:处理#开头的指令,展开头文件(g++ -E)
- 编译:将源代码转为汇编代码(g++ -S)
- 汇编:将汇编代码转为机器码(g++ -c)
- 链接:合并多个目标文件生成可执行程序
在VS Code中配置C++环境时,需要特别注意编译器路径和调试器设置。推荐使用MSVC或MinGW-w64作为Windows平台编译器,Linux/macOS则默认使用GCC/Clang。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 现代C++核心语法精要
2.1 变量与基本数据类型
C++作为静态类型语言,所有变量必须先声明后使用。基础数据类型包括:
- 整型:int(4字节)、short(2字节)、long long(8字节)
- 浮点型:float(4字节)、double(8字节)
- 字符型:char(1字节)、wchar_t(宽字符)
- 布尔型:bool(true/false)
C++11引入了类型推导关键字auto和decltype,可以简化复杂类型的声明:
cpp复制auto x = 42; // x被推导为int
auto str = "hello"; // str被推导为const char*
decltype(x) y = x; // y的类型与x相同
2.2 引用与指针的深度解析
引用(reference)是C++区别于C的重要特性,它本质上是一个别名:
cpp复制int a = 10;
int &ref = a; // ref是a的引用
ref = 20; // 现在a的值变为20
指针与引用的关键区别:
- 指针可以为nullptr,引用必须绑定对象
- 指针可以重新指向,引用一旦绑定不可更改
- 指针需要解引用(*p),引用直接使用
- 指针有自己的内存地址,引用与被引用对象共享地址
现代C++推荐优先使用引用,仅在需要动态内存管理或可选参数时使用指针。
2.3 函数与Lambda表达式
C++函数支持多种高级特性:
- 默认参数:
void log(string msg, bool newline = true) - 函数重载:同名函数根据参数类型区分
- 内联函数:
inline关键字避免函数调用开销
C++11引入的lambda表达式极大简化了匿名函数的定义:
cpp复制auto sum = [](int a, int b) -> int {
return a + b;
};
cout << sum(3, 5); // 输出8
lambda可以捕获外部变量:
[=]值捕获[&]引用捕获[x, &y]混合捕获
3. 面向对象编程实践
3.1 类与对象的设计原则
一个完整的类定义通常包含:
- 成员变量(属性)
- 构造函数/析构函数
- 成员函数(方法)
- 访问修饰符(public/protected/private)
示例银行账户类:
cpp复制class BankAccount {
private:
string owner;
double balance;
public:
BankAccount(string name) : owner(name), balance(0) {}
void deposit(double amount) {
if(amount > 0) balance += amount;
}
bool withdraw(double amount) {
if(amount <= balance) {
balance -= amount;
return true;
}
return false;
}
double getBalance() const { return balance; }
};
3.2 继承与多态机制
C++通过虚函数实现运行时多态:
cpp复制class Shape {
public:
virtual double area() const = 0; // 纯虚函数
virtual ~Shape() {} // 虚析构函数
};
class Circle : public Shape {
double radius;
public:
Circle(double r) : radius(r) {}
double area() const override { return 3.14 * radius * radius; }
};
class Rectangle : public Shape {
double width, height;
public:
Rectangle(double w, double h) : width(w), height(h) {}
double area() const override { return width * height; }
};
使用基类指针调用派生类方法:
cpp复制Shape* shapes[2];
shapes[0] = new Circle(5);
shapes[1] = new Rectangle(4, 6);
for(auto shape : shapes) {
cout << shape->area() << endl;
delete shape;
}
3.3 移动语义与智能指针
C++11引入的移动语义解决了不必要的拷贝问题:
cpp复制class String {
char* data;
public:
// 移动构造函数
String(String&& other) noexcept : data(other.data) {
other.data = nullptr;
}
// 移动赋值运算符
String& operator=(String&& other) noexcept {
if(this != &other) {
delete[] data;
data = other.data;
other.data = nullptr;
}
return *this;
}
};
智能指针自动管理内存生命周期:
unique_ptr:独占所有权,不可复制shared_ptr:共享所有权,引用计数weak_ptr:不增加引用计数的观察者
cpp复制auto ptr = make_shared<string>("hello");
weak_ptr<string> wptr = ptr;
if(auto spt = wptr.lock()) { // 检查对象是否存活
cout << *spt << endl;
}
4. 标准模板库(STL)深度应用
4.1 容器类精讲
STL提供了多种高效的容器模板:
序列容器:
vector:动态数组,支持快速随机访问list:双向链表,高效插入/删除deque:双端队列,首尾操作高效
关联容器:
map:红黑树实现的键值对unordered_map:哈希表实现的键值对set:唯一键的集合
容器适配器:
stack:LIFO栈queue:FIFO队列priority_queue:优先级队列
示例:统计单词频率
cpp复制map<string, int> wordCount;
string word;
while(cin >> word) {
++wordCount[word];
}
for(const auto& pair : wordCount) {
cout << pair.first << ": " << pair.second << endl;
}
4.2 算法与迭代器
STL算法通过迭代器操作容器:
cpp复制vector<int> nums {3, 1, 4, 1, 5, 9, 2, 6};
// 排序
sort(nums.begin(), nums.end());
// 查找
auto it = find(nums.begin(), nums.end(), 5);
if(it != nums.end()) {
cout << "Found at position: " << it - nums.begin() << endl;
}
// 累加
int sum = accumulate(nums.begin(), nums.end(), 0);
C++17引入的并行算法可以充分利用多核CPU:
cpp复制vector<int> bigData(1000000);
// 并行排序
sort(execution::par, bigData.begin(), bigData.end());
4.3 字符串处理进阶
string类提供了丰富的操作方法:
cpp复制string s = "Hello C++";
s.append(" World"); // "Hello C++ World"
s.replace(6, 3, "Modern"); // "Hello Modern World"
// 字符串分割
string text = "apple,orange,banana";
size_t pos = 0;
while((pos = text.find(',')) != string::npos) {
string token = text.substr(0, pos);
cout << token << endl;
text.erase(0, pos + 1);
}
cout << text << endl;
C++17新增的string_view可以避免不必要的字符串拷贝:
cpp复制string_view sv = "This is a string view";
cout << sv.substr(5, 2); // "is"
5. 实战项目:简易学生管理系统
5.1 系统设计与类结构
我们设计一个包含三个核心类的系统:
Student:存储学生信息Course:课程信息与成绩管理StudentManager:主控制类
类关系图:
code复制StudentManager "1" *-- "0..*" Student
Student "0..*" -- "0..*" Course
Student类定义:
cpp复制class Student {
string id;
string name;
map<string, double> courses; // 课程名-成绩
public:
Student(string id, string name) : id(id), name(name) {}
void addCourse(string courseName, double score) {
courses[courseName] = score;
}
double getAverage() const {
if(courses.empty()) return 0;
double sum = accumulate(courses.begin(), courses.end(), 0.0,
[](double acc, const pair<string, double>& p) {
return acc + p.second;
});
return sum / courses.size();
}
// 其他getter/setter...
};
5.2 文件持久化实现
使用<fstream>实现数据存储与加载:
cpp复制class StudentManager {
vector<Student> students;
public:
void saveToFile(const string& filename) {
ofstream out(filename);
for(const auto& stu : students) {
out << stu.getId() << "," << stu.getName();
for(const auto& course : stu.getCourses()) {
out << "," << course.first << ":" << course.second;
}
out << "\n";
}
}
void loadFromFile(const string& filename) {
ifstream in(filename);
string line;
while(getline(in, line)) {
vector<string> parts;
stringstream ss(line);
string item;
while(getline(ss, item, ',')) {
parts.push_back(item);
}
if(parts.size() >= 2) {
Student stu(parts[0], parts[1]);
for(size_t i = 2; i < parts.size(); ++i) {
size_t pos = parts[i].find(':');
if(pos != string::npos) {
string name = parts[i].substr(0, pos);
double score = stod(parts[i].substr(pos+1));
stu.addCourse(name, score);
}
}
students.push_back(stu);
}
}
}
};
5.3 交互界面与异常处理
基于控制台的用户界面:
cpp复制void showMenu() {
cout << "1. 添加学生\n"
<< "2. 添加课程成绩\n"
<< "3. 查询学生信息\n"
<< "4. 保存数据\n"
<< "5. 加载数据\n"
<< "0. 退出\n";
}
int main() {
StudentManager manager;
int choice;
try {
do {
showMenu();
cin >> choice;
switch(choice) {
case 1: {
string id, name;
cout << "输入学号和姓名: ";
cin >> id >> name;
manager.addStudent(Student(id, name));
break;
}
// 其他case...
case 0:
cout << "系统退出\n";
break;
default:
cout << "无效选择\n";
}
} while(choice != 0);
} catch(const exception& e) {
cerr << "发生错误: " << e.what() << endl;
return 1;
}
return 0;
}
注意:实际项目中应该对用户输入进行更严格的验证,防止无效数据导致程序崩溃。
6. 性能优化与调试技巧
6.1 常见性能陷阱与解决方案
-
不必要的拷贝:
- 错误示例:
vector<string> filter(const vector<string>& items) - 正确做法:使用移动语义或返回智能指针
- 错误示例:
-
虚函数调用开销:
- 在性能关键路径上考虑使用CRTP模式替代虚函数
-
缓存不友好访问:
- 优先顺序访问连续内存(vector优于list)
- 使用
__builtin_prefetch预取数据
-
内存分配优化:
- 使用对象池或内存池技术
- 预分配vector容量(reserve())
6.2 多线程编程要点
C++11引入的线程支持:
cpp复制#include <thread>
#include <mutex>
mutex mtx;
int shared_data = 0;
void increment() {
lock_guard<mutex> lock(mtx);
++shared_data;
}
int main() {
vector<thread> threads;
for(int i = 0; i < 10; ++i) {
threads.emplace_back(increment);
}
for(auto& t : threads) {
t.join();
}
cout << shared_data << endl; // 输出10
return 0;
}
原子操作比互斥锁更高效:
cpp复制#include <atomic>
atomic<int> counter(0);
void safe_increment() {
counter.fetch_add(1, memory_order_relaxed);
}
6.3 调试与性能分析工具
-
GDB调试:
- 断点设置:
break filename:line - 查看变量:
print variable - 回溯调用栈:
bt
- 断点设置:
-
Valgrind内存检查:
bash复制
valgrind --leak-check=full ./your_program -
gprof性能分析:
bash复制
g++ -pg your_program.cpp -o your_program ./your_program gprof your_program gmon.out > analysis.txt -
现代工具链:
- AddressSanitizer:内存错误检测
- ThreadSanitizer:数据竞争检测
- CPU Profiler:热点函数分析
7. 现代C++新特性实践
7.1 C++17结构化绑定
简化多返回值处理:
cpp复制tuple<int, string, double> getData() {
return {42, "answer", 3.14};
}
auto [num, str, val] = getData();
cout << num << str << val << endl;
适用于map遍历:
cpp复制map<string, int> scores = {{"Alice", 90}, {"Bob", 85}};
for(const auto& [name, score] : scores) {
cout << name << ": " << score << endl;
}
7.2 C++20概念与范围库
概念(Concepts)约束模板参数:
cpp复制template<typename T>
concept Numeric = is_integral_v<T> || is_floating_point_v<T>;
template<Numeric T>
T square(T x) { return x * x; }
范围库(Ranges)提供函数式编程支持:
cpp复制#include <ranges>
#include <algorithm>
vector<int> nums = {3, 1, 4, 1, 5, 9, 2, 6};
auto even = nums | views::filter([](int x){ return x%2 == 0; })
| views::transform([](int x){ return x*x; });
for(int x : even) {
cout << x << " "; // 输出16 4 36
}
7.3 协程(C++20)
协程实现异步编程:
cpp复制#include <coroutine>
generator<int> range(int start, int end) {
for(int i = start; i < end; ++i) {
co_yield i;
}
}
int main() {
for(int i : range(1, 10)) {
cout << i << " ";
}
return 0;
}
协程特别适合实现:
- 惰性求值序列
- 异步I/O操作
- 状态机实现
- 事件驱动编程
8. 工程实践与设计模式
8.1 RAII资源管理
资源获取即初始化(RAII)是C++核心范式:
cpp复制class FileHandle {
FILE* file;
public:
explicit FileHandle(const char* filename, const char* mode)
: file(fopen(filename, mode)) {
if(!file) throw runtime_error("File open failed");
}
~FileHandle() { if(file) fclose(file); }
// 禁用拷贝
FileHandle(const FileHandle&) = delete;
FileHandle& operator=(const FileHandle&) = delete;
// 允许移动
FileHandle(FileHandle&& other) noexcept : file(other.file) {
other.file = nullptr;
}
void write(const string& data) {
if(fwrite(data.data(), 1, data.size(), file) != data.size()) {
throw runtime_error("Write failed");
}
}
};
8.2 常用设计模式实现
单例模式(线程安全版):
cpp复制class Logger {
static mutex mtx;
static unique_ptr<Logger> instance;
Logger() = default;
public:
static Logger& getInstance() {
lock_guard<mutex> lock(mtx);
if(!instance) {
instance.reset(new Logger());
}
return *instance;
}
void log(const string& message) {
cout << message << endl;
}
};
unique_ptr<Logger> Logger::instance;
mutex Logger::mtx;
工厂模式:
cpp复制class ShapeFactory {
public:
virtual unique_ptr<Shape> create() = 0;
virtual ~ShapeFactory() = default;
};
class CircleFactory : public ShapeFactory {
double radius;
public:
explicit CircleFactory(double r) : radius(r) {}
unique_ptr<Shape> create() override {
return make_unique<Circle>(radius);
}
};
8.3 单元测试与代码质量
Google Test框架示例:
cpp复制#include <gtest/gtest.h>
TEST(StringTest, DefaultConstructor) {
MyString s;
EXPECT_EQ(0, s.length());
EXPECT_STREQ("", s.c_str());
}
TEST(MathTest, Factorial) {
EXPECT_EQ(1, factorial(0));
EXPECT_EQ(120, factorial(5));
}
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
代码质量工具链:
- clang-format:统一代码风格
- clang-tidy:静态代码分析
- cppcheck:潜在错误检测
- include-what-you-use:头文件优化
9. 跨平台开发与系统编程
9.1 文件系统操作
C++17 filesystem库:
cpp复制#include <filesystem>
namespace fs = std::filesystem;
void listFiles(const fs::path& dir) {
for(const auto& entry : fs::directory_iterator(dir)) {
cout << entry.path().filename() << " "
<< (entry.is_directory() ? "[DIR]" : "")
<< endl;
}
}
int main() {
fs::create_directory("test");
fs::copy("source.txt", "test/dest.txt");
listFiles(".");
return 0;
}
9.2 网络编程基础
使用Boost.Asio实现TCP客户端:
cpp复制#include <boost/asio.hpp>
using namespace boost::asio;
using ip::tcp;
void fetchData(const string& host, const string& port) {
io_service io;
tcp::resolver resolver(io);
tcp::socket socket(io);
connect(socket, resolver.resolve(host, port));
string request = "GET / HTTP/1.1\r\nHost: " + host + "\r\n\r\n";
write(socket, buffer(request));
streambuf response;
read_until(socket, response, "\r\n");
istream resp_stream(&response);
string http_version;
unsigned status_code;
resp_stream >> http_version >> status_code;
cout << "Status: " << status_code << endl;
}
9.3 进程与线程控制
创建子进程:
cpp复制#include <unistd.h>
int main() {
pid_t pid = fork();
if(pid == 0) { // 子进程
execl("/bin/ls", "ls", "-l", nullptr);
} else if(pid > 0) { // 父进程
wait(nullptr); // 等待子进程结束
}
return 0;
}
线程池实现:
cpp复制class ThreadPool {
vector<thread> workers;
queue<function<void()>> tasks;
mutex queue_mutex;
condition_variable condition;
bool stop = false;
public:
explicit ThreadPool(size_t threads) {
for(size_t i = 0; i < threads; ++i) {
workers.emplace_back([this] {
while(true) {
function<void()> task;
{
unique_lock<mutex> lock(queue_mutex);
condition.wait(lock, [this] {
return stop || !tasks.empty();
});
if(stop && tasks.empty()) return;
task = move(tasks.front());
tasks.pop();
}
task();
}
});
}
}
~ThreadPool() {
{
unique_lock<mutex> lock(queue_mutex);
stop = true;
}
condition.notify_all();
for(auto& worker : workers) {
worker.join();
}
}
template<class F>
void enqueue(F&& f) {
{
unique_lock<mutex> lock(queue_mutex);
tasks.emplace(forward<F>(f));
}
condition.notify_one();
}
};
10. 图形界面与游戏开发入门
10.1 Qt框架基础
创建简单窗口:
cpp复制#include <QApplication>
#include <QLabel>
int main(int argc, char** argv) {
QApplication app(argc, argv);
QLabel label("Hello Qt!");
label.setWindowTitle("First App");
label.resize(200, 100);
label.show();
return app.exec();
}
信号与槽机制:
cpp复制class Counter : public QObject {
Q_OBJECT
int value;
public:
Counter() : value(0) {}
void increment() {
++value;
emit valueChanged(value);
}
signals:
void valueChanged(int newValue);
};
class Display : public QObject {
Q_OBJECT
public slots:
void showValue(int value) {
qDebug() << "Current value:" << value;
}
};
int main() {
Counter counter;
Display display;
QObject::connect(&counter, &Counter::valueChanged,
&display, &Display::showValue);
counter.increment(); // 输出"Current value: 1"
return 0;
}
10.2 OpenCV图像处理
读取并显示图像:
cpp复制#include <opencv2/opencv.hpp>
using namespace cv;
int main() {
Mat image = imread("test.jpg");
if(image.empty()) {
cerr << "Image not found" << endl;
return 1;
}
Mat gray;
cvtColor(image, gray, COLOR_BGR2GRAY);
namedWindow("Original", WINDOW_AUTOSIZE);
namedWindow("Gray", WINDOW_AUTOSIZE);
imshow("Original", image);
imshow("Gray", gray);
waitKey(0);
return 0;
}
人脸检测示例:
cpp复制void detectFaces(const string& imagePath) {
CascadeClassifier faceCascade;
if(!faceCascade.load("haarcascade_frontalface_default.xml")) {
cerr << "Error loading face cascade" << endl;
return;
}
Mat image = imread(imagePath);
Mat gray;
cvtColor(image, gray, COLOR_BGR2GRAY);
equalizeHist(gray, gray);
vector<Rect> faces;
faceCascade.detectMultiScale(gray, faces);
for(const auto& face : faces) {
rectangle(image, face, Scalar(0, 255, 0), 2);
}
imshow("Face Detection", image);
waitKey(0);
}
10.3 简单游戏开发框架
基于SDL2的游戏循环:
cpp复制#include <SDL2/SDL.h>
int main() {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow(
"Simple Game",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
800, 600,
SDL_WINDOW_SHOWN
);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
bool running = true;
while(running) {
SDL_Event event;
while(SDL_PollEvent(&event)) {
if(event.type == SDL_QUIT) {
running = false;
}
}
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
// 绘制游戏对象
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
SDL_Rect rect = {100, 100, 50, 50};
SDL_RenderFillRect(renderer, &rect);
SDL_RenderPresent(renderer);
SDL_Delay(16); // ~60FPS
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
11. 嵌入式与硬件编程
11.1 寄存器级操作
嵌入式开发中经常需要直接操作硬件寄存器:
cpp复制// 假设有以下寄存器定义
#define GPIO_BASE 0x40020000
#define GPIO_MODER *(volatile uint32_t*)(GPIO_BASE + 0x00)
#define GPIO_ODR *(volatile uint32_t*)(GPIO_BASE + 0x14)
void led_init() {
// 设置GPIO引脚为输出模式
GPIO_MODER &= ~(0x3 << (2 * 5)); // 清除模式位
GPIO_MODER |= (0x1 << (2 * 5)); // 设置为输出模式
}
void led_toggle() {
GPIO_ODR ^= (1 << 5); // 翻转LED状态
}
注意:实际嵌入式开发中,通常会使用厂商提供的头文件定义寄存器,而不是直接使用硬编码地址。
11.2 中断服务例程
C++中断处理示例:
cpp复制extern "C" void TIM2_IRQHandler() { // 必须使用C链接
if(TIM2->SR & TIM_SR_UIF) { // 检查更新中断标志
TIM2->SR &= ~TIM_SR_UIF; // 清除中断标志
led_toggle(); // 用户代码
}
}
void timer_init() {
// 配置定时器2
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
TIM2->PSC = 16000 - 1; // 预分频器
TIM2->ARR = 1000 - 1; // 自动重载值(1ms)
TIM2->DIER |= TIM_DIER_UIE; // 使能更新中断
NVIC_EnableIRQ(TIM2_IRQn); // 使能NVIC中断
TIM2->CR1 |= TIM_CR1_CEN; // 启动定时器
}
11.3 内存受限环境优化
嵌入式系统中的内存优化技巧:
- 使用
-ffunction-sections -fdata-sections编译选项 - 链接时使用
--gc-sections移除未使用代码 - 优先使用静态分配而非动态内存
- 使用位域压缩数据结构:
cpp复制struct SensorData {
uint32_t temperature : 10; // 10位存储温度
uint32_t humidity : 10; // 10位存储湿度
uint32_t status : 4; // 4位状态标志
uint32_t : 8; // 保留位
};
- 使用联合体(union)共享内存空间:
cpp复制union DataPacket {
struct {
uint8_t header;
uint16_t value;
uint8_t checksum;
} fields;
uint8_t bytes[4];
};
12. 模板元编程进阶
12.1 SFINAE与类型特征
SFINAE(替换失败不是错误)技术示例:
cpp复制template<typename T>
auto print(const T& value) -> decltype(cout << value, void()) {
cout << value << endl;
}
void print(...) {
cout << "[unprintable]" << endl;
}
int main() {
print(42); // 调用第一个版本
print(vector<int>()); // 调用第二个版本
return 0;
}
类型特征(type traits)应用:
cpp复制template<typename T>
void process(const T& value) {
if constexpr(is_pointer_v<T>) {
cout << "Pointer to " << *value << endl;
} else if constexpr(is_integral_v<T>) {
cout << "Integer: " << value << endl;
} else {
cout << "Other type" << endl;
}
}
12.2 变参模板与折叠表达式
变参模板示例:
cpp复制template<typename... Args>
void log(Args&&... args) {
(cout << ... << args) << endl; // C++17折叠表达式
}
int main() {
log("Error", ": ", 404, " Not Found"); // 输出"Error: 404 Not Found"
return 0;
}
实现编译期字符串连接:
cpp复制template<char... Chars>
struct FixedString {
static constexpr char value[] = {Chars..., '\0'};
};
template<typename T, T... Chars>
constexpr FixedString<Chars...> operator""_fs() {
return {};
}
auto str = "hello"_fs; // 类型为FixedString<'h','e','l','l','o'>
12.3 编译期计算与constexpr
constexpr函数示例:
cpp复制constexpr int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
int main() {
constexpr int x = factorial(5); // 编译期计算
int y = factorial(5); // 运行时计算
return 0;
}
编译期字符串处理:
cpp复制template<size_t N>
struct ConstString {
char str[N]{};
constexpr ConstString(const char(&s)[N]) {
for(size_t i = 0; i < N; ++i) str[i] = s[i];
}
constexpr size_t size() const { return N - 1; }
};
constexpr ConstString hello = "world";
static_assert(hello.size() == 5);
13. 并发编程模式
13.1 生产者-消费者模式
使用条件变量实现:
cpp复制template<typename T>
class Queue {
queue<T> items;
mutex mtx;
condition_variable cv;
bool done = false;
public:
void push(T item) {
lock_guard<mutex> lock(mtx);
items.push(move(item));
cv.notify_one();
}
bool pop(T& item) {
unique_lock<mutex> lock(mtx);
cv.wait(lock, [this]{ return !items.empty() || done; });
if(items.empty()) return false;
item = move(items.front());
items.pop();
return true;
}
void setDone() {
lock_guard<mutex> lock(mtx);
done = true;
cv.notify_all();
}
};
void producer(Queue<int>& q) {
for(int i = 0; i < 10; ++i) {
q.push(i);
this_thread::sleep_for(100ms);
}
q.setDone();
}
void consumer(Queue<int>& q) {
int item;
while(q.pop(item)) {
cout << "Got: " << item << endl;
}
}
13.2 异步任务与future
使用async启动异步任务:
cpp复制int compute(int x) {
this_thread::sleep_for(1s);
return x * x;
}
int main() {
auto fut = async(launch::async, compute, 42);
// 可以做其他工作...
cout << "Waiting for result..." << endl;
int result = fut.get();
cout << "Result: " << result << endl;
return 0;
}
packaged_task示例:
cpp复制int main() {
packaged_task<int(int)> task([](int x) {
return x * 2;
});
future<int> fut = task.get_future();
thread t(move(task), 21);
cout << "Result: " << fut.get() << endl;
t.join();
return 0;
}
13.3 原子操作与内存顺序
内存顺序示例:
cpp复制atomic<int> x(0), y(0);
int r1, r2;
void thread1() {
x.store(1, memory_order_relaxed);
r1 = y.load(memory_order_relaxed);
}
void thread2() {
y.store(1, memory_order_relaxed);
r2 = x.load(memory_order_relaxed);
}
int main() {
thread t1(thread1), t2(thread2);
t1.join(); t2.join();
cout << r1 << " " << r2 << endl; // 可能输出0 0
return 0;
}
使用memory_order_seq_cst保证顺序一致性:
code复制
