1. C++:从系统级开发到现代编程实践
第一次接触C++是在大学二年级的操作系统课程上,教授让我们用C++实现一个简单的内存分配器。当时被指针和内存管理折磨得死去活来,但也正是这种"贴近硬件"的编程体验,让我真正理解了计算机底层的工作原理。十五年过去了,C++依然是我工具箱中最锋利的武器——无论是开发高频交易系统,还是优化游戏引擎的渲染管线。
C++之所以能在Java、Python等现代语言的围攻下屹立不倒,关键在于它独特的定位:既提供了对硬件的直接控制能力,又支持高级抽象机制。最新统计显示,全球仍有超过400万活跃的C++开发者,在性能敏感领域(如游戏引擎、金融系统、自动驾驶)的市场占有率超过60%。这篇文章将带你深入C++的核心特性、现代用法和实战技巧,无论你是刚接触C++的新手,还是想了解最新标准特性的资深开发者,都能找到实用的内容。
提示:本文所有代码示例基于C++17标准,建议使用GCC 10+或Clang 12+编译器体验完整特性
2. C++核心特性深度解析
2.1 类型系统与内存模型
C++的类型系统远比表面看起来复杂。基本类型的大小实际上与实现相关,这也是许多跨平台问题的根源。比如在x86-64架构上:
cpp复制static_assert(sizeof(int) == 4); // 通常成立但不保证
static_assert(sizeof(void*) == 8); // 64位系统
现代C++推荐使用固定宽度整数类型:
cpp复制#include <cstdint>
int32_t precise_width; // 精确32位有符号整数
uint64_t large_id; // 无符号64位整数
内存对齐是另一个关键知识点。错误的对齐会导致性能下降甚至硬件异常:
cpp复制struct BadLayout {
char c; // 1字节
double d; // 8字节,可能需要在c后插入7字节填充
int i; // 4字节
}; // 可能占用24字节(取决于ABI)
struct alignas(16) Optimized {
double d;
int i;
}; // 编译器会优化布局
2.2 现代C++的面向对象实践
传统的OOP三特性(封装、继承、多态)在C++中有独特实现方式。以多态为例,虚函数表(vtable)的实现机制直接影响性能:
cpp复制class Shape {
public:
virtual ~Shape() = default; // 基类析构函数必须为virtual
virtual double area() const = 0;
// 非虚接口(NVI)模式
void draw() const {
preDraw(); // 公共前置处理
doDraw(); // 私有虚函数实现
}
private:
virtual void doDraw() const = 0;
};
现代C++更推荐组合优于继承:
cpp复制class Circle {
public:
explicit Circle(double r) : radius(r) {}
double area() const { return 3.14159 * radius * radius; }
private:
double radius;
};
// 使用组合代替继承
class ColoredCircle {
public:
ColoredCircle(Circle c, Color clr) : circle(c), color(clr) {}
double area() const { return circle.area(); }
private:
Circle circle;
Color color;
};
2.3 模板元编程实战技巧
C++模板是编译时计算的强大工具。下面是一个编译时字符串处理的例子:
cpp复制template <size_t N>
struct FixedString {
char buf[N + 1] = {};
constexpr FixedString(const char (&s)[N]) {
std::copy_n(s, N, buf);
}
constexpr operator const char*() const { return buf; }
};
// 编译时字符串连接
template <FixedString S1, FixedString S2>
struct Concat {
static constexpr char value[] = {S1[0], S1[1], S2[0], S2[1], 0};
};
constexpr auto hello = FixedString("Hello");
constexpr auto world = FixedString("World");
static_assert(Concat<hello, world>::value[0] == 'H');
C++20概念(concepts)大幅改善了模板错误信息:
cpp复制template <typename T>
concept Arithmetic = std::is_arithmetic_v<T>;
template <Arithmetic T>
T square(T x) { return x * x; } // 只接受算术类型
3. 现代C++开发实践
3.1 资源管理革命:从RAII到智能指针
手动new/delete的时代已经过去,现代C++的资源管理哲学是RAII(Resource Acquisition Is Initialization)。以下是智能指针的最佳实践:
cpp复制// 独占所有权
auto ptr = std::make_unique<Widget>(args...);
// 共享所有权
auto shared = std::make_shared<LargeObject>(...);
// 弱引用避免循环引用
std::weak_ptr<Node> weakNode = parent->child;
if (auto locked = weakNode.lock()) {
// 安全使用child
}
陷阱:避免在接口中直接传递智能指针,除非需要转移所有权。推荐的做法是:
cpp复制void process(const Widget& w); // 首选引用 void sink(std::unique_ptr<Widget> w); // 明确所有权转移
3.2 并发编程实战模式
C++11引入的线程支持库奠定了现代并发编程的基础。一个典型的生产者-消费者模式实现:
cpp复制std::queue<Data> queue;
std::mutex mtx;
std::condition_variable cv;
// 生产者线程
void producer() {
while (auto data = get_data()) {
{
std::lock_guard lock(mtx);
queue.push(std::move(data));
}
cv.notify_one();
}
}
// 消费者线程
void consumer() {
while (true) {
std::unique_lock lock(mtx);
cv.wait(lock, []{ return !queue.empty(); });
auto data = std::move(queue.front());
queue.pop();
lock.unlock();
process(data);
}
}
C++20引入了更高级的并发抽象:
cpp复制std::atomic<std::shared_ptr<Data>> atomicPtr; // 原子智能指针
std::counting_semaphore<10> sem; // 计数信号量
std::latch completionLatch(5); // 线程同步原语
3.3 性能优化关键技巧
-
缓存友好设计:
- 使用
std::vector代替链表(除非频繁中间插入) - 结构体字段按访问频率和大小排序
- 避免虚假共享(false sharing):
cpp复制struct alignas(64) CacheLine { // 典型缓存行大小 int counter; // 填充剩余空间 char padding[64 - sizeof(int)]; };
- 使用
-
编译器优化提示:
cpp复制#define likely(x) __builtin_expect(!!(x), 1) // GCC/Clang if (likely(!buffer.empty())) { // 快速路径 } -
SIMD向量化:
cpp复制#include <immintrin.h> void simdAdd(float* a, float* b, float* c, size_t n) { for (size_t i = 0; i < n; i += 8) { __m256 va = _mm256_load_ps(a + i); __m256 vb = _mm256_load_ps(b + i); __m256 vc = _mm256_add_ps(va, vb); _mm256_store_ps(c + i, vc); } }
4. 工业级C++开发规范
4.1 构建系统最佳实践
现代C++项目推荐使用CMake作为构建系统。一个模块化的CMake配置示例:
cmake复制cmake_minimum_required(VERSION 3.15)
project(ModernCpp LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # 生成compile_commands.json
add_library(core STATIC
src/core/utils.cpp
src/core/algorithm.cpp
)
target_include_directories(core PUBLIC include)
target_compile_options(core PRIVATE -Wall -Wextra -Wpedantic)
add_executable(demo apps/demo.cpp)
target_link_libraries(demo PRIVATE core)
4.2 静态分析与代码规范
-
clang-tidy配置示例:
yaml复制Checks: > -*, clang-analyzer-*, modernize-*, performance-*, readability-* WarningsAsErrors: '*' HeaderFilterRegex: 'include/.*' -
Google Test单元测试框架集成:
cpp复制TEST(AlgorithmTest, SortTest) { std::vector<int> v = {5, 3, 1, 4, 2}; quick_sort(v.begin(), v.end()); EXPECT_THAT(v, ElementsAre(1, 2, 3, 4, 5)); }
4.3 跨平台开发要点
-
条件编译模式:
cpp复制#if defined(_WIN32) #define PATH_SEPARATOR '\\' #elif defined(__unix__) #define PATH_SEPARATOR '/' #endif -
ABI兼容性技巧:
- 使用PIMPL模式隐藏实现细节
- 避免在接口中使用STL容器
- 提供C风格接口封装
5. C++20/23新特性实战
5.1 协程(Coroutines)
C++20协程为异步编程带来革命性变化。一个简单的生成器模式实现:
cpp复制#include <coroutine>
template <typename T>
struct Generator {
struct promise_type {
T current_value;
auto yield_value(T value) {
current_value = value;
return std::suspend_always{};
}
auto initial_suspend() { return std::suspend_always{}; }
auto final_suspend() noexcept { return std::suspend_always{}; }
Generator get_return_object() { return Generator{this}; }
void unhandled_exception() { std::terminate(); }
void return_void() {}
};
using Handle = std::coroutine_handle<promise_type>;
Handle coro;
explicit Generator(promise_type* p)
: coro(Handle::from_promise(*p)) {}
~Generator() { if (coro) coro.destroy(); }
bool next() {
if (!coro.done()) {
coro.resume();
return !coro.done();
}
return false;
}
T value() const { return coro.promise().current_value; }
};
Generator<int> range(int start, int end) {
for (int i = start; i < end; ++i)
co_yield i;
}
// 使用示例
void demo() {
auto gen = range(1, 10);
while (gen.next()) {
std::cout << gen.value() << " ";
}
}
5.2 概念(Concepts)与约束
概念彻底改变了模板编程的体验:
cpp复制template <typename T>
concept Drawable = requires(T t, std::ostream& os) {
{ t.draw(os) } -> std::same_as<void>;
};
template <Drawable T>
void render(const T& obj) {
obj.draw(std::cout);
}
class Circle {
public:
void draw(std::ostream& os) const { os << "○"; }
};
// 编译时检查类型是否满足概念
static_assert(Drawable<Circle>);
5.3 模块(Modules)
模块化终于让C++摆脱了头文件包含的束缚:
cpp复制// math.ixx
export module math;
export namespace math {
int add(int a, int b) { return a + b; }
double sqrt(double x);
}
// math.cpp
module math;
namespace math {
double sqrt(double x) { /* 实现 */ }
}
// main.cpp
import math;
int main() {
math::add(1, 2);
}
6. C++工程实践中的陷阱与解决方案
6.1 内存问题诊断
-
AddressSanitizer使用:
bash复制
g++ -fsanitize=address -g demo.cpp ASAN_OPTIONS=detect_leaks=1 ./a.out -
Valgrind内存检查:
bash复制
valgrind --leak-check=full --show-leak-kinds=all ./program
6.2 多线程调试技巧
-
ThreadSanitizer检测数据竞争:
bash复制
g++ -fsanitize=thread -g threaded.cpp -
死锁检测模式:
cpp复制std::mutex m1, m2; void thread1() { std::scoped_lock lock(m1, m2); // C++17死锁避免 // ... }
6.3 二进制兼容性问题
-
版本管理策略:
cpp复制// 显式版本命名空间 namespace library_v1 { class Interface { /*...*/ }; } -
类型擦除技术:
cpp复制class AnyDrawable { struct Concept { virtual ~Concept() = default; virtual void draw(std::ostream&) const = 0; }; template <typename T> struct Model final : Concept { /*...*/ }; std::unique_ptr<Concept> pimpl; public: template <typename T> AnyDrawable(T obj) : pimpl(std::make_unique<Model<T>>(std::move(obj))) {} void draw(std::ostream& os) const { pimpl->draw(os); } };
7. C++生态系统与工具链
7.1 编译器选择指南
| 编译器 | 优势领域 | 最新特性支持 | 典型应用场景 |
|---|---|---|---|
| GCC | 标准符合性 | C++23部分 | Linux系统开发 |
| Clang | 错误诊断 | C++23领先 | 跨平台开发 |
| MSVC | Windows集成 | C++20完整 | 游戏开发 |
| ICC | 数值计算优化 | C++17稳定 | 科学计算 |
7.2 必备开发工具
-
调试工具:
- GDB/LLDB命令行调试器
- Qt Creator/VSCode图形化调试界面
-
性能分析:
- perf (Linux性能计数器)
- VTune (Intel处理器深度分析)
-
代码审查:
- SonarQube静态分析
- CodeCollaborator在线评审
7.3 依赖管理方案
-
vcpkg包管理:
bash复制vcpkg install fmt range-v3 -
Conan包管理器:
bash复制
conan install boost/1.79.0@ -
Bazel构建系统:
python复制cc_library( name = "core", srcs = ["core.cpp"], hdrs = ["core.h"], deps = ["@boost//:filesystem"], )
8. 从C++到其他语言的互操作
8.1 Python扩展开发
使用pybind11创建Python扩展模块:
cpp复制#include <pybind11/pybind11.h>
int add(int a, int b) { return a + b; }
PYBIND11_MODULE(example, m) {
m.def("add", &add, "A function that adds two numbers");
}
编译命令:
bash复制g++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix)
8.2 WebAssembly编译
使用Emscripten将C++编译为WebAssembly:
cpp复制#include <emscripten.h>
EMSCRIPTEN_KEEPALIVE
int fibonacci(int n) {
if (n <= 1) return n;
return fibonacci(n-1) + fibonacci(n-2);
}
编译命令:
bash复制emcc -O3 -s WASM=1 -s EXPORTED_FUNCTIONS="['_fibonacci']" fib.cpp -o fib.js
8.3 Java本地接口(JNI)
C++与Java互操作示例:
cpp复制#include <jni.h>
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_NativeLib_getMessage(JNIEnv* env, jobject) {
return env->NewStringUTF("Hello from C++!");
}
9. C++性能优化实战案例
9.1 热路径优化
一个XML解析器的优化历程:
-
初始版本:使用
std::regex匹配标签cpp复制std::regex tag_regex("<([^>]+)>"); std::smatch matches; if (std::regex_search(text, matches, tag_regex)) { // 处理匹配 } -
优化版本:手写状态机
cpp复制enum class ParserState { Text, TagOpen, TagContent }; void parse(const char* str) { ParserState state = ParserState::Text; const char* tag_start = nullptr; for (; *str; ++str) { switch (state) { case ParserState::Text: if (*str == '<') { state = ParserState::TagOpen; tag_start = str; } break; // 其他状态处理... } } } -
最终版本:SIMD加速扫描
cpp复制__m128i open_angle = _mm_set1_epi8('<'); for (; p + 16 < end; p += 16) { __m128i chunk = _mm_loadu_si128((const __m128i*)p); __m128i mask = _mm_cmpeq_epi8(chunk, open_angle); int bitmask = _mm_movemask_epi8(mask); while (bitmask) { int pos = __builtin_ctz(bitmask); process_tag(p + pos); bitmask &= bitmask - 1; } }
9.2 内存访问模式优化
矩阵转置的不同实现性能对比:
-
朴素实现:
cpp复制void transpose_naive(int* dst, const int* src, int N) { for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) dst[j*N + i] = src[i*N + j]; } -
分块优化:
cpp复制void transpose_block(int* dst, const int* src, int N, int block=32) { for (int bi = 0; bi < N; bi += block) for (int bj = 0; bj < N; bj += block) for (int i = bi; i < bi + block; ++i) for (int j = bj; j < bj + block; ++j) dst[j*N + i] = src[i*N + j]; } -
SIMD加速:
cpp复制void transpose_simd(int* dst, const int* src, int N) { for (int i = 0; i < N; i += 8) { for (int j = 0; j < N; j += 8) { __m256i row0 = _mm256_loadu_si256((__m256i*)(src + (i+0)*N + j)); // 加载其他7行... // 转置8x8块... _mm256_storeu_si256((__m256i*)(dst + j*N + i), row0); // 存储其他列... } } }
10. C++设计模式现代实现
10.1 策略模式与std::function
传统策略模式的现代C++实现:
cpp复制class PaymentStrategy {
public:
virtual ~PaymentStrategy() = default;
virtual void pay(int amount) const = 0;
};
// 现代替代方案
using PaymentHandler = std::function<void(int)>;
class ShoppingCart {
public:
void setPayment(PaymentHandler handler) {
payment_ = std::move(handler);
}
void checkout(int total) {
if (payment_) payment_(total);
}
private:
PaymentHandler payment_;
};
// 使用示例
void demo() {
ShoppingCart cart;
cart.setPayment([](int amount) {
std::cout << "Paid " << amount << " via credit card\n";
});
cart.checkout(100);
}
10.2 观察者模式与信号/槽
基于C++11的轻量级观察者实现:
cpp复制template <typename... Args>
class Signal {
using Slot = std::function<void(Args...)>;
std::vector<Slot> slots_;
public:
void connect(Slot slot) {
slots_.push_back(std::move(slot));
}
void emit(Args... args) {
for (auto& slot : slots_)
slot(args...);
}
};
class Button {
public:
Signal<> onClick;
void click() { onClick.emit(); }
};
void demo() {
Button btn;
btn.onClick.connect([] { std::cout << "Button clicked!\n"; });
btn.click();
}
10.3 依赖注入与模板元编程
编译时依赖注入框架示例:
cpp复制template <typename... Dependencies>
class Service {
std::tuple<Dependencies...> deps_;
public:
explicit Service(Dependencies... deps) : deps_(std::move(deps)...) {}
template <typename Dep>
Dep& get() { return std::get<Dep>(deps_); }
void operation() {
auto& logger = get<Logger>();
logger.log("Operation started");
// 使用其他依赖...
}
};
// 使用示例
void demo() {
Logger logger;
Database db;
Service<Logger, Database> service(logger, db);
service.operation();
}
11. C++模板元编程进阶
11.1 SFINAE与类型特征
现代C++之前的类型检测技术:
cpp复制template <typename T>
class has_serialize {
template <typename U>
static auto test(int) -> decltype(std::declval<U>().serialize(), std::true_type{});
template <typename>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(0))::value;
};
template <typename T>
typename std::enable_if<has_serialize<T>::value, std::string>::type
serialize(const T& obj) { return obj.serialize(); }
template <typename T>
typename std::enable_if<!has_serialize<T>::value, std::string>::type
serialize(const T& obj) { return "default"; }
C++20概念简化版:
cpp复制template <typename T>
concept Serializable = requires(const T& t) {
{ t.serialize() } -> std::convertible_to<std::string>;
};
template <Serializable T>
std::string serialize(const T& obj) { return obj.serialize(); }
template <typename T>
std::string serialize(const T& obj) { return "default"; }
11.2 编译时字符串处理
实现编译时字符串哈希:
cpp复制constexpr uint32_t fnv1a(const char* str, uint32_t hash = 0x811C9DC5) {
return *str ? fnv1a(str + 1, (hash ^ *str) * 0x01000193) : hash;
}
// 使用示例
constexpr uint32_t color_hash = fnv1a("color");
static_assert(fnv1a("hello") == 0x4f9f2cab);
11.3 模板特化与模式匹配
实现类型安全的variant访问:
cpp复制template <typename... Ts>
struct overload : Ts... { using Ts::operator()...; };
template <typename... Ts>
overload(Ts...) -> overload<Ts...>;
void demo() {
std::variant<int, std::string> v = "hello";
std::visit(overload{
[](int i) { std::cout << "int: " << i; },
[](const std::string& s) { std::cout << "string: " << s; }
}, v);
}
12. C++异常处理与错误管理
12.1 异常安全保证
-
基本异常安全:
cpp复制class DatabaseConnection { Handle* handle; public: void update(const Record& r) { Handle* new_handle = clone_handle(handle); // 不影响原状态 try { db_update(new_handle, r); delete handle; handle = new_handle; // 提交更改 } catch (...) { delete new_handle; // 回滚 throw; } } }; -
强异常安全:
cpp复制std::vector<int> safe_insert(const std::vector<int>& v, int pos, int val) { std::vector<int> copy = v; // 先复制 copy.insert(copy.begin() + pos, val); // 修改副本 return copy; // NRVO优化避免额外复制 }
12.2 错误处理替代方案
-
预期值模式:
cpp复制template <typename T, typename E> class Expected { union { T value; E error; }; bool has_value; public: // 访问方法... }; Expected<File, Error> open_file(const char* path); -
系统错误码:
cpp复制std::error_code ec; auto file = std::fopen("data.txt", "r", ec); if (ec) { std::cerr << "Error: " << ec.message(); }
13. C++与硬件交互
13.1 内联汇编实战
x86-64平台下的性能关键代码:
cpp复制uint64_t rdtsc() {
uint32_t lo, hi;
asm volatile (
"rdtsc" : "=a"(lo), "=d"(hi)
);
return ((uint64_t)hi << 32) | lo;
}
void memcpy_optimized(void* dst, const void* src, size_t n) {
asm volatile (
"rep movsb"
: "+D"(dst), "+S"(src), "+c"(n)
: : "memory"
);
}
13.2 内存屏障与原子操作
无锁队列的实现核心:
cpp复制template <typename T>
class LockFreeQueue {
struct Node {
T data;
std::atomic<Node*> next;
};
std::atomic<Node*> head;
std::atomic<Node*> tail;
public:
void push(const T& value) {
Node* new_node = new Node{value, nullptr};
Node* old_tail = tail.exchange(new_node, std::memory_order_acq_rel);
old_tail->next.store(new_node, std::memory_order_release);
}
bool pop(T& result) {
Node* old_head = head.load(std::memory_order_relaxed);
if (old_head == nullptr) return false;
if (head.compare_exchange_strong(
old_head, old_head->next,
std::memory_order_release,
std::memory_order_relaxed)) {
result = old_head->data;
delete old_head;
return true;
}
return false;
}
};
14. C++代码生成与反射
14.1 编译期反射技术
使用预处理器生成类型信息:
cpp复制#define REFLECT(T) \
template <> struct TypeInfo<T> { \
static constexpr std::string_view name = #T; \
static constexpr auto members = std::make_tuple();
#define MEMBER(name) \
std::make_pair(#name, [](auto& obj) -> auto& { return obj.name; })
struct Point {
int x;
int y;
};
REFLECT(Point)
MEMBER(x),
MEMBER(y)
);
14.2 运行时代码生成
使用LLVM生成机器码:
cpp复制#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
llvm::Function* create_add_func(llvm::Module* module) {
auto& context = module->getContext();
auto* func = llvm::Function::Create(
llvm::FunctionType::get(
llvm::Type::getInt32Ty(context),
{llvm::Type::getInt32Ty(context), llvm::Type::getInt32Ty(context)},
false),
llvm::Function::ExternalLinkage,
"add",
module);
auto* entry = llvm::BasicBlock::Create(context, "entry", func);
llvm::IRBuilder<> builder(entry);
auto* sum = builder.CreateAdd(
func->getArg(0), func->getArg(1), "sum");
builder.CreateRet(sum);
return func;
}
15. C++跨语言接口设计
15.1 C接口封装模式
安全的C接口封装:
cpp复制// C++实现
class Database {
public:
void connect(const std::string& url);
Result query(const std::string& sql);
};
// C接口
extern "C" {
struct CDatabase;
CDatabase* db_create();
void db_connect(CDatabase* db, const char* url);
void db_destroy(CDatabase* db);
}
// 实现
CDatabase* db_create() {
try {
return reinterpret_cast<CDatabase*>(new Database);
} catch (...) { return nullptr; }
}
void db_connect(CDatabase* db, const char* url) {
try {
reinterpret_cast<Database*>(db)->connect(url);
} catch (...) { /* 转换为错误码 */ }
}
15.2 COM组件开发
基本的COM接口实现:
cpp复制struct ICalculator : IUnknown {
virtual HRESULT STDMETHODCALLTYPE Add(int a, int b, int* result) = 0;
};
class Calculator : public ICalculator {
ULONG ref_ = 0;
public:
// IUnknown方法
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv) override {
if (riid == IID_IUnknown || riid == __uuidof(ICalculator)) {
*ppv = static_cast<ICalculator*>(this);
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
ULONG STDMETHODCALLTYPE AddRef() override { return ++ref_; }
ULONG STDMETHODCALLTYPE Release() override {
if (--ref_ == 0) { delete this; return 0; }
return ref_;
}
// ICalculator方法
HRESULT STDMETHODCALLTYPE Add(int a, int b, int* result) override {
if (!result) return E_POINTER;
*result = a + b;
return S_OK;
}
};
16. C++测试驱动开发
16.1 Google Test高级用法
类型参数化测试:
cpp复制template <typename T>
class StackTest : public testing::Test {
protected:
Stack<T> stack;
};
using Types = testing::Types<int, double, std::string>;
TYPED_TEST_SUITE(StackTest, Types);
TYPED_TEST(StackTest, PushPop) {
TypeParam value = {};
this->stack.push(value);
EXPECT_EQ(this->stack.pop(), value);
}
16.2 模拟对象技术
使用gmock创建模拟接口:
cpp复制class Database {
public:
virtual ~Database() = default;
virtual bool connect(const std::string& url) = 0;
virtual Result query(const std::string& sql) = 0;
};
class MockDatabase : public Database {
public:
MOCK_METHOD(bool, connect, (const std::string&), (override));
MOCK_METHOD(Result, query, (const std::string&), (override));
};
TEST(DatabaseTest, Connection) {
MockDatabase db;
EXPECT_CALL(db, connect("test.db"))
.WillOnce(Return(true));
DatabaseManager manager(&db);
EXPECT_TRUE(manager.initialize("test.db"));
}
17. C++安全编程实践
17.1 缓冲区溢出防护
安全字符串处理:
cpp复制void safe_copy(char* dest, const char* src, size_t dest_size) {
if (dest_size == 0) return;
size_t i = 0;
for (; i < dest_size - 1 && src[i]; ++i) {
dest[i] = src[i];
}
dest[i] = '\0';
}
// 现代替代方案
std::string safe_string(const char* src) {
return src ? std::string(src) : std::string();
}
17.2 密码学安全API
使用OpenSSL进行安全哈希:
cpp复制#include <openssl/sha.h>
std::string sha256(const std::string& input) {
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX ctx;
SHA256_Init(&ctx);
SHA256_Update(&ctx, input.data(), input.size());
SHA256_Final(hash, &ctx);
std::string result;
result.reserve(SHA256_DIGEST_LENGTH * 2);
for (unsigned char c : hash) {
result += "0123456789abcdef"[c >> 4];
result += "0123456789abcdef"[c & 0x0f];
}
return result;
}
18. C++嵌入式开发
18.1 寄存器操作模式
安全的寄存器访问抽象:
cpp复制template <typename T, uintptr_t Addr>
struct Register {
static_assert(std::is_unsigned_v<T>, "Register type must be unsigned");
static volatile T* ptr() {
return reinterpret_cast<volatile T*>(Addr);
}
static T read() { return *ptr(); }
static void write(T value) { *ptr() = value; }
class Bit {
T mask_;
public:
constexpr explicit Bit(T bit) : mask_(1 << bit) {}
void set() { *ptr() |= mask_; }
void clear() { *ptr()