1. 为什么需要整理C++高频代码片段?
作为一个在C++领域摸爬滚打多年的老码农,我深刻体会到:真正高效的开发不是每次从零开始造轮子,而是建立自己的代码武器库。那些看似简单的代码片段,往往能在关键时刻帮你节省数小时的调试时间。
记得刚入行时,我总喜欢在Stack Overflow上反复搜索同一个问题。直到有天发现,自己三个月内竟然搜索了17次"如何用C++分割字符串"。这种重复劳动让我意识到:必须把高频使用的代码片段系统化整理起来。
2. 字符串处理三剑客
2.1 字符串分割的三种姿势
字符串处理是日常开发中最常见的需求之一。以下是经过多年实战验证的三种分割方案:
cpp复制// 方法1:使用stringstream(适合简单分隔)
std::vector<std::string> splitByStream(const std::string& s, char delimiter) {
std::vector<std::string> tokens;
std::string token;
std::istringstream tokenStream(s);
while (std::getline(tokenStream, token, delimiter)) {
tokens.push_back(token);
}
return tokens;
}
// 方法2:使用find/substr(处理复杂分隔)
std::vector<std::string> splitByFind(const std::string& s,
const std::string& delimiter) {
std::vector<std::string> tokens;
size_t start = 0, end = 0;
while ((end = s.find(delimiter, start)) != std::string::npos) {
tokens.push_back(s.substr(start, end - start));
start = end + delimiter.length();
}
tokens.push_back(s.substr(start));
return tokens;
}
// 方法3:C++17的string_view版本(高性能场景)
std::vector<std::string_view> splitByView(std::string_view s,
std::string_view delimiter) {
std::vector<std::string_view> tokens;
size_t start = 0, end = 0;
while ((end = s.find(delimiter, start)) != std::string_view::npos) {
tokens.push_back(s.substr(start, end - start));
start = end + delimiter.length();
}
tokens.push_back(s.substr(start));
return tokens;
}
实战经验:方法3的性能比方法1快3-5倍,特别是在处理大文本时。但要注意string_view的生命周期管理,避免悬垂引用。
2.2 字符串格式化进阶技巧
C++20之前的标准库缺少方便的字符串格式化工具,这是我们经常需要自己封装的另一个痛点:
cpp复制// 支持任意参数的格式化函数
template <typename... Args>
std::string formatString(const std::string& format, Args... args) {
size_t size = snprintf(nullptr, 0, format.c_str(), args...) + 1;
std::unique_ptr<char[]> buf(new char[size]);
snprintf(buf.get(), size, format.c_str(), args...);
return std::string(buf.get(), buf.get() + size - 1);
}
// C++20的format用法(推荐)
auto message = std::format("The answer is {}.", 42);
避坑指南:传统sprintf系列函数存在缓冲区溢出风险,务必先用snprintf计算长度。C++20的format是类型安全的更好选择。
2.3 字符串编码转换大全
处理多语言环境时,编码转换是躲不开的坑。这里给出Windows/Linux通用的解决方案:
cpp复制// UTF-8与宽字符互转(跨平台)
std::wstring utf8ToWstring(const std::string& str) {
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
return converter.from_bytes(str);
}
std::string wstringToUtf8(const std::wstring& str) {
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
return converter.to_bytes(str);
}
// 处理Windows下的ANSI编码
std::string ansiToUtf8(const std::string& str) {
#ifdef _WIN32
int size = MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0);
std::wstring wstr(size, 0);
MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, &wstr[0], size);
return wstringToUtf8(wstr);
#else
return str; // Linux默认UTF-8
#endif
}
编码陷阱:Windows控制台默认使用ANSI编码,而现代应用多用UTF-8。混合使用时务必显式转换,否则中文必然乱码。
3. 容器操作黑魔法
3.1 高效容器合并技巧
合并多个vector时,如何避免不必要的拷贝?reserve+insert组合拳:
cpp复制template <typename T>
std::vector<T> mergeVectors(const std::vector<std::vector<T>>& input) {
std::vector<T> result;
size_t totalSize = 0;
for (const auto& vec : input) {
totalSize += vec.size();
}
result.reserve(totalSize);
for (const auto& vec : input) {
result.insert(result.end(),
std::make_move_iterator(vec.begin()),
std::make_move_iterator(vec.end()));
}
return result;
}
性能对比:在合并10个各含1万元素的vector时,预先reserve比直接insert快8倍。
3.2 容器元素快速去重
利用unordered_set的特性实现O(n)复杂度去重:
cpp复制template <typename T>
void uniqueVector(std::vector<T>& vec) {
std::unordered_set<T> seen;
auto end = std::remove_if(vec.begin(), vec.end(),
[&seen](const T& value) {
return !seen.insert(value).second;
});
vec.erase(end, vec.end());
}
进阶技巧:如果需要保持原顺序,用set代替unordered_set。对于自定义类型,记得重载hash函数。
3.3 map的多键查询优化
当需要根据value反向查找key时,可以构建双向map:
cpp复制template <typename Key, typename Value>
class BiDirectionalMap {
std::unordered_map<Key, Value> keyToValue;
std::unordered_map<Value, Key> valueToKey;
public:
void insert(const Key& key, const Value& value) {
keyToValue[key] = value;
valueToKey[value] = key;
}
const Value& getValue(const Key& key) const {
return keyToValue.at(key);
}
const Key& getKey(const Value& value) const {
return valueToKey.at(value);
}
};
使用场景:ID与名称映射、枚举值与字符串转换等需要双向查询的场景。
4. 智能指针实战技巧
4.1 自定义删除器的妙用
管理特殊资源时,自定义删除器比RAII类更轻量:
cpp复制// 管理文件句柄
auto fileDeleter = [](FILE* fp) {
if(fp) fclose(fp);
};
std::unique_ptr<FILE, decltype(fileDeleter)>
filePtr(fopen("data.bin", "rb"), fileDeleter);
// 管理Win32句柄
struct HandleDeleter {
void operator()(HANDLE h) const {
if (h != INVALID_HANDLE_VALUE) {
CloseHandle(h);
}
}
};
using UniqueHandle = std::unique_ptr<void, HandleDeleter>;
内存管理黄金法则:任何资源获取操作都应该立即交给智能指针管理,避免裸指针逃逸。
4.2 shared_ptr的循环引用破解
使用weak_ptr打破循环引用:
cpp复制class Node {
public:
std::vector<std::shared_ptr<Node>> children;
std::weak_ptr<Node> parent; // 关键点
~Node() {
std::cout << "Node destroyed\n";
}
};
void testCycle() {
auto parent = std::make_shared<Node>();
auto child = std::make_shared<Node>();
parent->children.push_back(child);
child->parent = parent; // 使用weak_ptr而非shared_ptr
}
内存泄漏检测:在Linux下可以用valgrind --leak-check=full验证。
4.3 实现作用域守卫模式
C++11版本的scope_guard:
cpp复制template <typename Func>
class ScopeGuard {
Func f;
bool active;
public:
ScopeGuard(Func func) : f(std::move(func)), active(true) {}
~ScopeGuard() { if(active) f(); }
void dismiss() { active = false; }
ScopeGuard(const ScopeGuard&) = delete;
ScopeGuard& operator=(const ScopeGuard&) = delete;
ScopeGuard(ScopeGuard&& other)
: f(std::move(other.f)), active(other.active) {
other.dismiss();
}
};
template <typename Func>
ScopeGuard<Func> makeScopeGuard(Func f) {
return ScopeGuard<Func>(std::move(f));
}
// 使用示例
void safeFileOperation() {
FILE* fp = fopen("temp.txt", "w");
auto guard = makeScopeGuard([&] {
if(fp) fclose(fp);
std::cout << "Resource released\n";
});
// 业务代码
if(error_occurred) return;
guard.dismiss(); // 正常完成时取消自动释放
}
5. 多线程编程核心片段
5.1 线程安全队列实现
生产者-消费者模型的基石:
cpp复制template <typename T>
class ThreadSafeQueue {
std::queue<T> queue;
mutable std::mutex mutex;
std::condition_variable cond;
public:
void push(T value) {
std::lock_guard<std::mutex> lock(mutex);
queue.push(std::move(value));
cond.notify_one();
}
bool try_pop(T& value) {
std::lock_guard<std::mutex> lock(mutex);
if(queue.empty()) return false;
value = std::move(queue.front());
queue.pop();
return true;
}
void wait_and_pop(T& value) {
std::unique_lock<std::mutex> lock(mutex);
cond.wait(lock, [this]{ return !queue.empty(); });
value = std::move(queue.front());
queue.pop();
}
bool empty() const {
std::lock_guard<std::mutex> lock(mutex);
return queue.empty();
}
};
性能优化:多个生产者时用notify_all替代notify_one,但要注意虚假唤醒问题。
5.2 异步任务与future高级用法
实现超时控制的异步调用:
cpp复制template <typename Func, typename... Args>
auto asyncWithTimeout(Func&& func, Args&&... args,
std::chrono::milliseconds timeout)
-> std::optional<decltype(func(args...))>
{
using RetType = decltype(func(args...));
std::promise<RetType> promise;
auto future = promise.get_future();
std::thread([&] {
try {
promise.set_value(func(std::forward<Args>(args)...));
} catch (...) {
promise.set_exception(std::current_exception());
}
}).detach();
if(future.wait_for(timeout) == std::future_status::ready) {
return future.get();
}
return std::nullopt;
}
// 使用示例
auto result = asyncWithTimeout([]{
std::this_thread::sleep_for(500ms);
return 42;
}, 300ms);
if(result) {
std::cout << "Got value: " << *result << "\n";
} else {
std::cout << "Timeout!\n";
}
5.3 线程池经典实现
固定大小线程池核心逻辑:
cpp复制class ThreadPool {
std::vector<std::thread> workers;
ThreadSafeQueue<std::function<void()>> tasks;
std::atomic<bool> stop{false};
public:
explicit ThreadPool(size_t threads) {
for(size_t i = 0; i < threads; ++i) {
workers.emplace_back([this] {
while(true) {
std::function<void()> task;
tasks.wait_and_pop(task);
if(stop && !task) return;
task();
}
});
}
}
template <typename F, typename... Args>
auto enqueue(F&& f, Args&&... args)
-> std::future<decltype(f(args...))>
{
using RetType = decltype(f(args...));
auto task = std::make_shared<std::packaged_task<RetType()>>(
std::bind(std::forward<F>(f), std::forward<Args>(args)...));
std::future<RetType> res = task->get_future();
tasks.push([task](){ (*task)(); });
return res;
}
~ThreadPool() {
stop = true;
for(size_t i = 0; i < workers.size(); ++i) {
tasks.push(nullptr); // 唤醒线程退出
}
for(auto& worker : workers) {
worker.join();
}
}
};
线程池黄金法则:任务应该是无状态的纯函数,避免共享可变状态。必须共享时使用线程安全容器。
6. 性能优化关键代码
6.1 内存池基础实现
减少malloc调用的简单内存池:
cpp复制class MemoryPool {
struct Block {
Block* next;
};
Block* freeList = nullptr;
size_t blockSize;
std::vector<char*> chunks;
public:
explicit MemoryPool(size_t size) : blockSize(size) {}
void* allocate() {
if(!freeList) {
const size_t chunkSize = 1024;
char* chunk = new char[chunkSize * blockSize];
chunks.push_back(chunk);
for(size_t i = 0; i < chunkSize; ++i) {
Block* block = reinterpret_cast<Block*>(chunk + i * blockSize);
block->next = freeList;
freeList = block;
}
}
Block* block = freeList;
freeList = freeList->next;
return block;
}
void deallocate(void* ptr) {
Block* block = static_cast<Block*>(ptr);
block->next = freeList;
freeList = block;
}
~MemoryPool() {
for(char* chunk : chunks) {
delete[] chunk;
}
}
};
适用场景:频繁创建/销毁固定大小对象的场景,如网络数据包、游戏实体等。
6.2 缓存行对齐优化
避免false sharing的两种方法:
cpp复制// 方法1:C++11 alignas
struct alignas(64) CacheLineAlignedData {
std::atomic<int> counter;
char padding[64 - sizeof(std::atomic<int>)];
};
// 方法2:手动填充
template <typename T>
struct Padded {
T value;
char padding[64 - sizeof(T)];
};
// 使用示例
Padded<std::atomic<int>> counters[4];
性能测试:在多线程频繁访问相邻原子变量时,对齐后性能可提升5-10倍。
6.3 内联汇编性能热点优化
针对特定CPU架构的优化示例(x86-64):
cpp复制// 快速字符串长度计算
inline size_t fastStrLen(const char* str) {
size_t len = 0;
asm volatile (
"repnz scasb\n"
: "=c"(len)
: "D"(str), "a"(0), "c"(-1)
: "cc"
);
return -len - 1;
}
// 内存屏障示例
inline void memoryBarrier() {
asm volatile ("" ::: "memory");
}
内联汇编注意事项:现代编译器通常能生成更好的代码,除非在极端性能敏感场景,否则应优先使用标准C++。使用内联汇编会降低可移植性。
7. 实用工具代码集锦
7.1 高性能日志工具类
兼顾线程安全和性能的日志工具:
cpp复制class Logger {
std::ofstream logFile;
std::mutex mutex;
std::atomic<bool> asyncMode{false};
ThreadSafeQueue<std::string> logQueue;
std::thread writerThread;
void writerLoop() {
std::string msg;
while(true) {
logQueue.wait_and_pop(msg);
if(msg.empty()) break; // 停止信号
logFile << msg << std::flush;
}
}
public:
explicit Logger(const std::string& filename)
: logFile(filename, std::ios::app) {
if(!logFile) throw std::runtime_error("Cannot open log file");
writerThread = std::thread(&Logger::writerLoop, this);
}
~Logger() {
if(asyncMode) {
logQueue.push(""); // 发送停止信号
writerThread.join();
}
}
void setAsync(bool async) { asyncMode = async; }
template <typename... Args>
void log(Args&&... args) {
std::ostringstream oss;
(oss << ... << args) << '\n';
std::string msg = oss.str();
if(asyncMode) {
logQueue.push(std::move(msg));
} else {
std::lock_guard<std::mutex> lock(mutex);
logFile << msg << std::flush;
}
}
};
7.2 跨平台高精度计时器
性能分析必备工具:
cpp复制class HighResTimer {
using Clock = std::chrono::high_resolution_clock;
Clock::time_point start;
public:
HighResTimer() : start(Clock::now()) {}
void reset() { start = Clock::now(); }
template <typename Unit = std::chrono::milliseconds>
auto elapsed() const {
return std::chrono::duration_cast<Unit>(Clock::now() - start);
}
static uint64_t systemTime() {
#ifdef _WIN32
FILETIME ft;
GetSystemTimeAsFileTime(&ft);
return (static_cast<uint64_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
#else
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
#endif
}
};
7.3 类型安全的枚举反射
将枚举转换为字符串:
cpp复制#define ENUM_REFLECT(EnumType) \
template <> struct EnumTraits<EnumType> { \
static constexpr std::array<std::pair<EnumType, const char*>, _count> mapping = { _map }; \
static constexpr size_t count = _count; \
}; \
inline const char* enumToString(EnumType value) { \
for(const auto& item : EnumTraits<EnumType>::mapping) { \
if(item.first == value) return item.second; \
} \
return "Unknown"; \
} \
inline EnumType stringToEnum(const std::string& str) { \
for(const auto& item : EnumTraits<EnumType>::mapping) { \
if(str == item.second) return item.first; \
} \
throw std::invalid_argument("Invalid enum string"); \
}
// 使用示例
enum class Color { Red, Green, Blue };
#define _count 3
#define _map { {Color::Red, "Red"}, {Color::Green, "Green"}, {Color::Blue, "Blue"} }
template <> struct EnumTraits<Color>;
ENUM_REFLECT(Color)
8. 现代C++特性集萃
8.1 结构化绑定应用实例
解析复杂返回值的新姿势:
cpp复制// 返回多个值的函数
auto getConfig() -> std::tuple<std::string, int, bool> {
return {"config.json", 1024, true};
}
// 传统方式
auto config = getConfig();
std::string file = std::get<0>(config);
int size = std::get<1>(config);
bool enabled = std::get<2>(config);
// 结构化绑定方式
auto [file, size, enabled] = getConfig();
// 结合map遍历
std::map<int, std::string> idToName = {{1, "Alice"}, {2, "Bob"}};
for(const auto& [id, name] : idToName) {
std::cout << id << ": " << name << "\n";
}
8.2 constexpr实用技巧
编译期字符串哈希:
cpp复制constexpr uint32_t hashString(const char* str, uint32_t seed = 0) {
uint32_t hash = seed;
while(*str) {
hash = (hash * 31) + *str++;
}
return hash;
}
// 使用示例
switch(hashString(inputStr)) {
case hashString("option1"): /*...*/ break;
case hashString("option2"): /*...*/ break;
default: /*...*/
}
编译期计算优势:可以用于模板参数、case标签等需要编译期常量的场景。
8.3 概念约束模板示例
用C++20概念约束模板参数:
cpp复制template <typename T>
concept Arithmetic = requires(T a, T b) {
{ a + b } -> std::same_as<T>;
{ a - b } -> std::same_as<T>;
{ a * b } -> std::same_as<T>;
{ a / b } -> std::same_as<T>;
};
template <Arithmetic T>
T calculate(T a, T b) {
return (a + b) * (a - b);
}
// 错误用法检查
static_assert(Arithmetic<int>); // 通过
static_assert(!Arithmetic<std::string>); // 不通过
9. 工程化必备代码
9.1 单例模式线程安全实现
Meyers' Singleton改进版:
cpp复制template <typename T>
class Singleton {
protected:
Singleton() = default;
~Singleton() = default;
public:
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
static T& instance() {
static T instance;
return instance;
}
};
// 使用示例
class ConfigManager : public Singleton<ConfigManager> {
friend class Singleton<ConfigManager>;
ConfigManager() { /* 初始化 */ }
public:
std::string getConfig(const std::string& key);
// 其他接口...
};
9.2 对象池模板实现
通用对象池模板:
cpp复制template <typename T, size_t ChunkSize = 1024>
class ObjectPool {
struct Chunk {
std::array<T, ChunkSize> objects;
std::bitset<ChunkSize> used;
Chunk* next = nullptr;
};
Chunk* head = nullptr;
std::mutex mutex;
Chunk* allocateChunk() {
auto* chunk = new Chunk;
chunk->next = head;
head = chunk;
return chunk;
}
public:
template <typename... Args>
T* construct(Args&&... args) {
std::lock_guard<std::mutex> lock(mutex);
for(Chunk* chunk = head; chunk; chunk = chunk->next) {
for(size_t i = 0; i < ChunkSize; ++i) {
if(!chunk->used.test(i)) {
chunk->used.set(i);
return new (&chunk->objects[i])
T(std::forward<Args>(args)...);
}
}
}
// 没有空闲位置,分配新chunk
Chunk* newChunk = allocateChunk();
newChunk->used.set(0);
return new (&newChunk->objects[0])
T(std::forward<Args>(args)...);
}
void destroy(T* obj) {
std::lock_guard<std::mutex> lock(mutex);
for(Chunk* chunk = head; chunk; chunk = chunk->next) {
if(obj >= std::begin(chunk->objects) &&
obj < std::end(chunk->objects)) {
ptrdiff_t index = obj - std::begin(chunk->objects);
obj->~T();
chunk->used.reset(index);
return;
}
}
throw std::invalid_argument("Object not from this pool");
}
~ObjectPool() {
while(head) {
Chunk* next = head->next;
delete head;
head = next;
}
}
};
9.3 插件系统基础框架
动态库加载的跨平台封装:
cpp复制class PluginLoader {
using PluginEntry = void(*)();
#ifdef _WIN32
using Handle = HMODULE;
Handle openLib(const std::string& path) {
return LoadLibraryA(path.c_str());
}
void closeLib(Handle h) { FreeLibrary(h); }
PluginEntry getSymbol(Handle h, const char* name) {
return (PluginEntry)GetProcAddress(h, name);
}
#else
using Handle = void*;
Handle openLib(const std::string& path) {
return dlopen(path.c_str(), RTLD_LAZY);
}
void closeLib(Handle h) { dlclose(h); }
PluginEntry getSymbol(Handle h, const char* name) {
return (PluginEntry)dlsym(h, name);
}
#endif
std::unordered_map<std::string, Handle> loadedPlugins;
public:
void load(const std::string& path) {
Handle handle = openLib(path.c_str());
if(!handle) throw std::runtime_error("Cannot load plugin");
auto entry = getSymbol(handle, "plugin_entry");
if(!entry) {
closeLib(handle);
throw std::runtime_error("Invalid plugin format");
}
loadedPlugins[path] = handle;
entry(); // 调用插件入口函数
}
void unload(const std::string& path) {
auto it = loadedPlugins.find(path);
if(it != loadedPlugins.end()) {
closeLib(it->second);
loadedPlugins.erase(it);
}
}
~PluginLoader() {
for(auto& [path, handle] : loadedPlugins) {
closeLib(handle);
}
}
};
10. 测试与调试利器
10.1 内存泄漏检测工具
简单但有效的内存跟踪器:
cpp复制class MemoryTracker {
static std::unordered_map<void*, std::pair<size_t, std::string>> allocations;
static std::mutex mutex;
public:
static void* trackAlloc(size_t size, const char* file, int line) {
void* ptr = malloc(size);
std::lock_guard<std::mutex> lock(mutex);
allocations[ptr] = {size, std::string(file) + ":" + std::to_string(line)};
return ptr;
}
static void trackFree(void* ptr) {
std::lock_guard<std::mutex> lock(mutex);
auto it = allocations.find(ptr);
if(it != allocations.end()) {
allocations.erase(it);
}
free(ptr);
}
static void reportLeaks() {
std::lock_guard<std::mutex> lock(mutex);
if(!allocations.empty()) {
std::cerr << "Memory leaks detected:\n";
for(const auto& [ptr, info] : allocations) {
std::cerr << info.first << " bytes at " << ptr
<< " allocated at " << info.second << "\n";
}
}
}
};
// 重载operator new/delete
void* operator new(size_t size, const char* file, int line) {
return MemoryTracker::trackAlloc(size, file, line);
}
void* operator new[](size_t size, const char* file, int line) {
return operator new(size, file, line);
}
void operator delete(void* ptr) noexcept {
MemoryTracker::trackFree(ptr);
}
void operator delete[](void* ptr) noexcept {
operator delete(ptr);
}
#define new new(__FILE__, __LINE__)
10.2 单元测试框架核心
微型测试框架实现:
cpp复制class TestRunner {
struct TestCase {
std::string name;
std::function<void()> func;
};
std::vector<TestCase> tests;
int passed = 0;
public:
template <typename Func>
void addTest(const std::string& name, Func func) {
tests.push_back({name, func});
}
void runAll() {
for(auto& test : tests) {
std::cout << "Running " << test.name << "... ";
try {
test.func();
std::cout << "OK\n";
++passed;
} catch(const std::exception& e) {
std::cout << "FAIL: " << e.what() << "\n";
}
}
std::cout << "\nSummary: " << passed << "/"
<< tests.size() << " passed\n";
}
};
#define TEST_CASE(name) \
void name(); \
namespace { \
struct name##_Register { \
name##_Register() { \
TestRunner::instance().addTest(#name, &name); \
} \
} name##_instance; \
} \
void name()
// 使用示例
TEST_CASE(testAddition) {
if(1 + 1 != 2) throw std::runtime_error("Math is broken");
}
10.3 性能剖析宏集合
简单实用的性能分析工具:
cpp复制#define PROFILE_SCOPE(name) \
static int64_t totalTime##__LINE__ = 0; \
static int callCount##__LINE__ = 0; \
HighResTimer timer##__LINE__; \
struct ScopeExit##__LINE__ { \
~ScopeExit##__LINE__() { \
auto elapsed = timer##__LINE__.elapsed().count(); \
totalTime##__LINE__ += elapsed; \
if(++callCount##__LINE__ % 100 == 0) { \
std::cout << "[" << name << "] Avg: " \
<< totalTime##__LINE__ / callCount##__LINE__ \
<< "ns, Total: " << totalTime##__LINE__ << "ns\n"; \
} \
} \
} scopeExit##__LINE__
#define PROFILE_FUNCTION() PROFILE_SCOPE(__FUNCTION__)
// 使用示例
void expensiveFunction() {
PROFILE_FUNCTION();
// 耗时操作...
}
11. 跨平台兼容性处理
11.1 系统API抽象层
文件系统操作的跨平台封装:
cpp复制namespace FileSystem {
bool exists(const std::string& path) {
#ifdef _WIN32
DWORD attrs = GetFileAttributesA(path.c_str());
return attrs != INVALID_FILE_ATTRIBUTES;
#else
struct stat st;
return stat(path.c_str(), &st) == 0;
#endif
}
uint64_t fileSize(const std::string& path) {
#ifdef _WIN32
WIN32_FILE_ATTRIBUTE_DATA fad;
if(!GetFileAttributesExA(path.c_str(),
GetFileExInfoStandard, &fad)) {
throw std::runtime_error("Cannot get file size");
}
return (static_cast<uint64_t>(fad.nFileSizeHigh) << 32) |
fad.nFileSizeLow;
#else
struct stat st;
if(stat(path.c_str(), &st) != 0) {
throw std::runtime_error("Cannot get file size");
}
return st.st_size;
#endif
}
std::string currentPath() {
#ifdef _WIN32
char buf[MAX_PATH];
GetCurrentDirectoryA(MAX_PATH, buf);
return buf;
#else
char buf[PATH_MAX];
if(!getcwd(buf, PATH_MAX)) {
throw std::runtime_error("Cannot get current directory");
}
return buf;
#endif
}
}
11.2 字节序转换工具
网络编程必备:
cpp复制inline uint16_t swap16(uint16_t value) {
return (value << 8) | (value >> 8);
}
inline uint32_t swap32(uint32_t value) {
return ((value & 0xFF000000) >> 24) |
((value & 0x00FF0000) >> 8) |
((value & 0x0000FF00) << 8) |
((value & 0x000000FF) << 24);
}
inline uint64_t swap64(uint64_t value) {
return ((value & 0xFF00000000000000ULL) >> 56) |
((value & 0x00FF000000000000ULL) >> 40) |
((value & 0x0000FF0000000000ULL) >> 24) |
((value & 0x000000FF00000000ULL) >> 8) |
((value & 0x00000000FF000000ULL) << 8) |
((value & 0x0000000000FF0000ULL) << 24) |
((value & 0x000000000000FF00ULL) << 40) |
((value & 0x00000000000000FFULL) << 56);
}
template <typename T>
T hostToNetwork(T value) {
static_assert(std::is_integral_v<T>, "Only integer types supported");
if constexpr (sizeof(T) == 1) {
return value;
} else if constexpr (sizeof(T) == 2) {
return swap16(value);
} else if constexpr (sizeof(T) == 4) {
return swap32(value);
} else if constexpr (sizeof(T) == 8) {
return swap64(value);
}
}
template <typename T>
T networkToHost(T value) {
return hostToNetwork(value); // 对称操作
}
11.3 系统信息获取
CPU和内存信息采集:
cpp复制struct SystemInfo {
unsigned cpuCores;
uint64_t totalMemory;
std::string osName;
static SystemInfo get() {
SystemInfo info;
#ifdef _WIN32
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
info.cpuCores = sysInfo.dwNumberOfProcessors;
MEMORYSTATUSEX memInfo;
memInfo.dwLength = sizeof(memInfo);
GlobalMemoryStatusEx(&memInfo);
info.totalMemory = memInfo.ullTotalPhys;
info.osName = "Windows";
#elif defined(__linux__)
info.cpuCores = sysconf(_SC_NPROCESSORS_ONLN);
long pages = sysconf(_SC_PHYS_PAGES);
long pageSize = sysconf(_SC_PAGE_SIZE);
info.totalMemory = pages * pageSize;
struct utsname uts;
uname(&uts);
info.osName = uts.sysname;
#endif
return info;
}
};
12. 代码片段管理建议
12.1 如何组织代码片段库
经过多年实践,我总结出这套代码片段管理
