C++ 常用编程技巧总结
涵盖 C++11/14/17/20 现代特性与最佳实践
一、现代 C++ 核心特性
1.1 auto 关键字
auto i = 42;
auto d = 3.14;
auto s = "hello";
auto v = std::vector<int>{1, 2, 3};
std::map<std::string, int> m;
for (auto it = m.begin(); it != m.end(); ++it) { }
for (auto& item : container) { }
1.2 智能指针
#include <memory>
std::unique_ptr<int> p1 = std::make_unique<int>(42);
auto p2 = std::make_unique<int>(100);
auto sp1 = std::make_shared<int>(42);
auto sp2 = sp1;
std::weak_ptr<int> wp = sp1;
if (auto locked = wp.lock()) {
std::cout << *locked << std::endl;
}
std::unique_ptr<FILE, decltype(&fclose)> file(fopen("test.txt", "r"), &fclose);
1.3 右值引用与移动语义
class MyClass {
public:
MyClass(MyClass&& other) noexcept
: data_(std::move(other.data_)) {}
MyClass& operator=(MyClass&& other) noexcept {
if (this != &other) {
data_ = std::move(other.data_);
}
return *this;
}
private:
std::vector<int> data_;
};
template<typename T>
void wrapper(T&& arg) {
process(std::forward<T>(arg));
}
二、RAII 资源管理
2.1 RAII 模式
class ResourceGuard {
public:
ResourceGuard() { acquire(); }
~ResourceGuard() { release(); }
ResourceGuard(const ResourceGuard&) = delete;
ResourceGuard& operator=(const ResourceGuard&) = delete;
ResourceGuard(ResourceGuard&&) = default;
ResourceGuard& operator=(ResourceGuard&&) = default;
};
void processFile(const std::string& filename) {
std::ifstream file(filename);
if (!file) throw std::runtime_error("Cannot open file");
}
2.2 lock_guard vs unique_lock
#include <mutex>
std::mutex mtx;
{
std::lock_guard<std::mutex> lock(mtx);
}
{
std::unique_lock<std::mutex> lock(mtx);
lock.unlock();
lock.lock();
}
std::mutex mtx1, mtx2;
{
std::scoped_lock lock(mtx1, mtx2);
}
三、容器与算法
3.1 容器选择指南
| 容器 | 适用场景 | 时间复杂度 |
|---|
vector | 随机访问、尾部插入 | O(1) 访问,O(1) 尾插 |
deque | 双端操作 | O(1) 首尾插入 |
list | 频繁中间插入删除 | O(1) 插入删除 |
map/set | 有序查找 | O(log n) |
unordered_map/set | 快速查找 | O(1) 平均 |
3.2 vector 优化
std::vector<int> v;
v.reserve(1000);
for (int i = 0; i < 1000; ++i) {
v.push_back(i);
}
v.insert(v.end(),
boost::counting_iterator<int>(0),
boost::counting_iterator<int>(1000));
v.insert(v.end(), {1, 2, 3, 4, 5});
std::vector<std::string> vec;
vec.push_back(std::move(str));
vec.emplace_back("hello");
3.3 map 优化
std::map<std::string, int> m;
m.emplace("key", 42);
m.try_emplace("key", 42);
m.insert_or_assign("key", 42);
m.insert({{"a", 1}, {"b", 2}, {"c", 3}});
四、Lambda 表达式
4.1 Lambda 基础
auto f = [](int x) { return x * 2; };
int a = 10;
int b = 20;
auto f1 = [a, b]() { return a + b; };
auto f2 = [&a, b]() { a++; return a + b; };
auto f3 = [=]() { return a + b; };
auto f4 = [&]() { a++; b++; };
auto f5 = [=, &a]() { a++; return a + b; };
auto add = [](auto x, auto y) { return x + y; };
add(1, 2);
add(1.5, 2.5);
auto f6 = [p = std::make_unique<int>(42)]() { return *p; };
4.2 Lambda 高级用法
int result = [](int x, int y) {
return x + y;
}(1, 2);
auto factorial = [](auto self, int n) -> int {
return n <= 1 ? 1 : n * self(self, n - 1);
};
int fact5 = factorial(factorial, 5);
auto factorial2 = [](this auto&& self, int n) -> int {
return n <= 1 ? 1 : n * self(n - 1);
};
std::function<int(int, int)> op = [](int a, int b) { return a + b; };
auto op2 = std::make_unique<int(int, int)>([](int a, int b) { return a + b; });
五、模板编程
5.1 模板基础
template<typename T>
T max(T a, T b) {
return (a > b) ? a : b;
}
template<typename T, size_t N>
class Array {
T data[N];
public:
T& operator[](size_t i) { return data[i]; }
constexpr size_t size() const { return N; }
};
template<typename T>
constexpr T pi = T(3.14159265358979);
template<typename T>
using Vec = std::vector<T, std::allocator<T>>;
Vec<int> v;
5.2 可变参数模板
template<typename T>
void print(T t) {
std::cout << t << std::endl;
}
template<typename T, typename... Args>
void print(T t, Args... args) {
std::cout << t << ", ";
print(args...);
}
template<typename... Args>
auto sum(Args... args) {
return (... + args);
}
template<typename... Args>
void print_all(Args... args) {
(std::cout << ... << args) << std::endl;
}
5.3 SFINAE 与 Concepts
template<typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type
process(T t) {
return t * 2;
}
template<typename T>
requires std::integral<T>
T process(T t) {
return t * 2;
}
template<std::integral T>
T process(T t) {
return t * 2;
}
auto process(std::integral auto t) {
return t * 2;
}
template<typename T>
concept Numeric = std::is_arithmetic_v<T>;
template<Numeric T>
T add(T a, T b) { return a + b; }
六、编译期计算
6.1 constexpr
constexpr int MAX_SIZE = 100;
constexpr int factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
constexpr int fact5 = factorial(5);
class Point {
int x_, y_;
public:
constexpr Point(int x, int y) : x_(x), y_(y) {}
constexpr int x() const { return x_; }
constexpr int y() const { return y_; }
constexpr int distance() const { return x_ * x_ + y_ * y_; }
};
constexpr Point p(3, 4);
static_assert(p.distance() == 25);
6.2 if constexpr
template<typename T>
auto getValue(T t) {
if constexpr (std::is_pointer_v<T>) {
return *t;
} else if constexpr (std::is_integral_v<T>) {
return t * 2;
} else {
return t;
}
}
template<typename T>
void process(T t) {
if constexpr (std::is_same_v<T, int>) {
std::cout << "int: " << t << std::endl;
} else if constexpr (std::is_same_v<T, std::string>) {
std::cout << "string: " << t << std::endl;
}
}
6.3 编译期字符串
consteval int sqr(int n) {
return n * n;
}
int x = sqr(5);
constexpr size_t str_length(const char* str) {
size_t len = 0;
while (str[len]) ++len;
return len;
}
static_assert(str_length("hello") == 5);
七、性能优化
7.1 避免不必要拷贝
void process(const std::string& s);
void process(std::string s);
std::vector<std::string> getData() {
std::vector<std::string> result;
return result;
}
std::string createString() {
return std::string("hello");
}
void f(int x);
void f(const std::string& s);
void f(std::string& s);
void f(std::string s) { member_ = std::move(s); }
7.2 emplace_back vs push_back
std::vector<std::pair<int, std::string>> v;
v.push_back(std::make_pair(1, "hello"));
v.emplace_back(1, "hello");
struct Person {
std::string name;
int age;
Person(std::string n, int a) : name(std::move(n)), age(a) {}
};
std::vector<Person> people;
people.emplace_back("Alice", 30);
7.3 避免频繁内存分配
std::string result;
result.reserve(1000);
for (int i = 0; i < 100; ++i) {
result += std::to_string(i);
}
void process(std::string_view sv);
std::ostringstream oss;
oss.str().reserve(1024);
std::string s = std::format("Value: {}, {}", 1, 2);
7.4 算法优化
std::vector<int> v = {3, 1, 4, 1, 5};
std::sort(v.begin(), v.end());
auto it = std::find(v.begin(), v.end(), 4);
bool found = std::binary_search(v.begin(), v.end(), 4);
int count = std::count(v.begin(), v.end(), 1);
int cnt = std::count_if(v.begin(), v.end(), [](int x) { return x > 2; });
v.erase(std::remove(v.begin(), v.end(), 1), v.end());
v.erase(std::remove_if(v.begin(), v.end(),
[](int x) { return x % 2 == 0; }), v.end());
八、并发编程
8.1 线程基础
#include <thread>
#include <future>
#include <mutex>
#include <condition_variable>
std::thread t1([]() { });
t1.join();
std::jthread t2([]() { });
auto future = std::async(std::launch::async, []() {
return expensiveComputation();
});
auto result = future.get();
std::vector<std::future<int>> futures;
for (int i = 0; i < 10; ++i) {
futures.push_back(std::async(std::launch::async, [i]() {
return compute(i);
}));
}
8.2 同步原语
std::mutex mtx;
int counter = 0;
void increment() {
std::lock_guard<std::mutex> lock(mtx);
++counter;
}
std::shared_mutex rw_mtx;
void reader() {
std::shared_lock<std::shared_mutex> lock(rw_mtx);
}
void writer() {
std::unique_lock<std::shared_mutex> lock(rw_mtx);
}
std::condition_variable cv;
std::mutex cv_mtx;
bool ready = false;
void waitForReady() {
std::unique_lock<std::mutex> lock(cv_mtx);
cv.wait(lock, []{ return ready; });
}
void signalReady() {
{
std::lock_guard<std::mutex> lock(cv_mtx);
ready = true;
}
cv.notify_one();
}
8.3 原子操作
#include <atomic>
std::atomic<int> counter(0);
std::atomic<bool> flag(false);
counter.fetch_add(1);
counter.fetch_sub(1);
counter.exchange(10);
int expected = 10;
bool success = counter.compare_exchange_strong(expected, 20);
class SpinLock {
std::atomic_flag flag = ATOMIC_FLAG_INIT;
public:
void lock() { while (flag.test_and_set(std::memory_order_acquire)); }
void unlock() { flag.clear(std::memory_order_release); }
};
九、异常处理
9.1 异常最佳实践
throw std::runtime_error("Something went wrong");
try {
riskyOperation();
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
} catch (...) {
std::cerr << "Unknown error" << std::endl;
}
void safeFunction() noexcept {
}
static_assert(noexcept(safeFunction()));
9.2 RAII 异常安全
class Container {
std::vector<int> data_;
public:
void append(const std::vector<int>& items) {
std::vector<int> temp = data_;
temp.insert(temp.end(), items.begin(), items.end());
data_.swap(temp);
}
};
#include <gsl/gsl>
void process() {
auto guard = gsl::finally([]() { cleanup(); });
}
十、现代 C++ 特性速查
10.1 C++11
| 特性 | 说明 |
|---|
auto | 自动类型推导 |
nullptr | 空指针字面量 |
constexpr | 编译期计算 |
range-for | 范围 for 循环 |
| 智能指针 | unique_ptr, shared_ptr |
| 移动语义 | 右值引用, std::move |
| Lambda | 匿名函数 |
override/final | 虚函数控制 |
delete | 删除函数 |
enum class | 强类型枚举 |
10.2 C++14
| 特性 | 说明 |
|---|
| 泛型 lambda | [](auto x) |
make_unique | 智能指针工厂 |
| 二进制字面量 | 0b1010 |
| 数字分隔符 | 1'000'000 |
std::exchange | 原子交换 |
std::quoted | 引号IO操作 |
10.3 C++17
| 特性 | 说明 |
|---|
| 结构化绑定 | auto [a, b] = pair; |
if constexpr | 编译期条件 |
std::optional | 可选值 |
std::variant | 类型安全联合 |
std::any | 任意类型 |
std::string_view | 字符串视图 |
| 并行算法 | std::execution::par |
| 文件系统 | std::filesystem |
10.4 C++20
| 特性 | 说明 |
|---|
| Concepts | 概念约束 |
| Ranges | 范围库 |
| Coroutines | 协程 |
| Modules | 模块 |
std::format | 格式化 |
std::span | 数组视图 |
std::source_location | 源码位置 |
| 三向比较符 | <=> |
10.5 C++23
| 特性 | 说明 |
|---|
std::expected | 错误处理 |
std::print | 类型安全输出 |
| Deducing this | 显式对象参数 |
std::mdspan | 多维数组视图 |
std::flat_map/set | 扁平容器 |
if consteval | consteval条件 |
十一、常用代码片段
11.1 单例模式
class Singleton {
public:
static Singleton& instance() {
static Singleton inst;
return inst;
}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
private:
Singleton() = default;
};
11.2 工厂模式
template<typename Base, typename... Args>
class Factory {
public:
using Creator = std::function<std::unique_ptr<Base>(Args...)>;
void registerType(const std::string& name, Creator creator) {
creators_[name] = std::move(creator);
}
std::unique_ptr<Base> create(const std::string& name, Args... args) {
auto it = creators_.find(name);
if (it != creators_.end()) {
return it->second(std::forward<Args>(args)...);
}
return nullptr;
}
private:
std::unordered_map<std::string, Creator> creators_;
};
11.3 观察者模式
template<typename... Args>
class Signal {
public:
using Slot = std::function<void(Args...)>;
void connect(Slot slot) {
slots_.push_back(std::move(slot));
}
void emit(Args... args) {
for (auto& slot : slots_) {
slot(args...);
}
}
private:
std::vector<Slot> slots_;
};
Signal<int, std::string> signal;
signal.connect([](int id, const std::string& msg) {
std::cout << id << ": " << msg << std::endl;
});
signal.emit(1, "Hello");
11.4 PIMPL 模式
class Widget {
public:
Widget();
~Widget();
void doSomething();
private:
class Impl;
std::unique_ptr<Impl> pImpl_;
};
class Widget::Impl {
public:
void doSomething() { }
};
Widget::Widget() : pImpl_(std::make_unique<Impl>()) {}
Widget::~Widget() = default;
void Widget::doSomething() { pImpl_->doSomething(); }
11.5 延迟初始化
template<typename T>
class Lazy {
public:
template<typename... Args>
explicit Lazy(Args&&... args)
: args_(std::forward<Args>(args)...) {}
T& get() {
if (!value_) {
value_ = std::make_unique<T>(std::apply(
[this](auto&&... args) {
return T(std::forward<decltype(args)>(args)...);
}, args_));
}
return *value_;
}
private:
std::tuple<Args...> args_;
std::unique_ptr<T> value_;
};
十二、调试与测试
12.1 断言
assert(ptr != nullptr);
static_assert(sizeof(int) == 4, "int must be 4 bytes");
#define EXPECT(cond, msg) \
if (!(cond)) { \
std::cerr << "Assertion failed: " << #cond \
<< "\nMessage: " << msg \
<< "\nFile: " << __FILE__ \
<< "\nLine: " << __LINE__ << std::endl; \
std::abort(); \
}
12.2 日志
#define LOG(level, msg) \
std::cout << "[" << level << "] " \
<< __FILE__ << ":" << __LINE__ << " " \
<< msg << std::endl
LOG("INFO", "Processing started");
LOG("ERROR", "Failed to open file: " << filename);
#include <source_location>
void log(const std::string& message,
const std::source_location& loc = std::source_location::current()) {
std::cout << loc.file_name() << ":" << loc.line()
<< " " << message << std::endl;
}
总结
核心原则
| 原则 | 说明 |
|---|
| RAII | 资源获取即初始化 |
| 零开销 | 不为未使用的特性付费 |
| 值语义 | 优先使用值而非引用/指针 |
| const正确 | 尽可能使用 const |
| 异常安全 | 保证基本或强异常安全 |
| 现代C++ | 使用智能指针,避免裸指针和new/delete |
最佳实践
- ✅ 使用
auto 简化类型声明
- ✅ 优先使用智能指针管理资源
- ✅ 使用 RAII 包装资源
- ✅ 使用 STL 算法替代手写循环
- ✅ 使用
emplace 系列函数
- ✅ 使用
std::move 避免拷贝
- ✅ 使用
const 和 constexpr
- ✅ 使用现代 C++ 特性
文档生成时间:2026-03-26