wanghenshui/cppweeklynews/cppweeklynews

Claude Code and agent skill by wanghenshui/cppweeklynews

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Install

npx vskill@latest install wanghenshui/cppweeklynews/cppweeklynews

SKILL.md

C++ 开发技能指南

本文档从 C++ 中文周刊(第1期~第196期)中提炼的编码规范、设计模式、性能优化和避坑指南。
适用于日常 C++ 开发参考。

一、现代 C++ 编码规范

1.1 优先使用 range-based for 和 Ranges 库

传统 for 循环"过于灵活",容易引入 off-by-one、修改错误变量等 bug。编译器无法防止这些问题。

cpp
// ❌ 经典错误
for (auto i = 0; i <= vec.size(); ++i) // 应该是 <
use(vec[i]);
for (auto i = vec.size() - 1; i >= 0; --i) // 无符号数永远 >= 0,死循环!
use(vec[i]);
// ✅ 现代写法
for (auto const& rec : records)
use(rec);
// 反向迭代(C++20)
for (auto const& rec : std::views::reverse(records))
use(rec);
// 带索引迭代(C++23)
for (auto [i, rec] : std::views::enumerate(records))
use(i, rec);
// 多序列同时迭代(C++23)
for (auto [name, rec] : std::views::zip(names, records))
use(name, rec);

来源:第190期

1.2 用 std::source_location 替代 __FILE__ / __LINE__ 宏
cpp
// ❌ 传统宏方法
#define ASSERT(cond, msg) Assert(cond, msg, __FUNCTION__, __LINE__)
// ✅ C++20
void Assert(bool condition, std::string_view msg,
std::source_location loc = std::source_location::current()) {
if (!condition) {
std::clog << loc.function_name() << ':' << loc.line() << ": " << msg << '\n';
}
}
// 调用时不需要宏:
Assert(1 != 2, "Not met");

关键:std::source_location::current() 作为默认参数,在调用侧求值。

来源:第190期

1.3 constexpr + consteval 双路径设计
cpp
consteval size_t strlen_ct(const char* s) { // 纯编译期
size_t n = 0;
for (; s[n] != '\0'; ++n);
return n;
}
size_t strlen(const char* s); // 纯运行期
constexpr size_t strlen_dual(const char* s) { // 双路径
if consteval {
return strlen_ct(s); // 编译期路径
} else {
return strlen(s); // 运行期路径
}
}

constexpr 函数最好两种分支都实现,避免意外问题。

来源:第150期

1.4 用 std::expected 替代异常做错误处理(C++23)
cpp
std::expected<int, std::string> convertToInt(const std::string& input) {
int value{};
auto [ptr, ec] = std::from_chars(input.data(), input.data() + input.size(), value);
if (ec == std::errc())
return value;
if (ec == std::errc::invalid_argument)
return std::unexpected("Invalid number format");
if (ec == std::errc::result_out_of_range)
return std::unexpected("Number out of range");
return std::unexpected("Unknown conversion error");
}

来源:第150期

1.5 Concepts 和 requires 的正确用法
cpp
// 基本 requires
template <typename T>
requires std::integral<T>
auto debug_output(const T& t);
// requires requires(检测成员函数)
template <typename T>
requires requires(const T& t) { t.debug_output(); }
auto debug_output(const T& t);
// if constexpr + requires(编译期检测能力)
template <typename Cont, typename Rng>
void cont_assign(Cont& cont, Rng&& rng) {
cont.clear();
if constexpr (requires { cont.reserve(std::ranges::size(rng)); }) {
cont.reserve(std::ranges::size(rng));
}
for (auto&& elem : std::forward<Rng>(rng)) {
cont.push_back(std::forward<decltype(elem)>(elem));
}
}

来源:第170期

1.6 deducing this 消除成员函数重复(C++23)
cpp
// ❌ 传统写法:4个重载
struct Foo {
void bar() &;
void bar() &&;
void bar() const &;
void bar() const &&;
};
// ✅ C++23
template <typename T>
class Optional {
template <typename Self>
constexpr auto operator->(this Self&& self) {
return addressof(self.m_value);
}
};

来源:第50期

1.7 inline namespace 做版本控制
cpp
namespace gem {
inline namespace v1 {
struct Point { int x; int y; };
}
namespace v2 {
struct Point { int y; int x; }; // v2 改了布局
}
}
// 默认用 v1,需要时显式 gem::v2::Point

来源:第160期

1.8 小对象直接传值,不要 const T&

string_view、span、int、chrono::duration 等小对象,直接传值比传引用更高效。

来源:第50期


二、性能优化指南

2.1 火焰图驱动优化

RocksDB 优化案例(180s → 7.8s,23倍加速),每步用火焰图验证:

  1. Transaction Put → SST Writer(180s → 19.5s):消除锁和排序开销
  2. 关掉导入阶段不需要的过滤器和压缩(19.5s → 14.3s)
  3. fast_float 替换 sscanf(14.3s → 12s,16%提速)
  4. std::string → vector\<char\>(12s → 10.6s):消除 null terminator 维护开销
  5. 去掉热路径的运行期检查(10.6s → 8.7s)
  6. 消除 key 的隐藏拷贝(8.7s → 7.8s)

Key takeaways:

  • 避免热路径中的虚函数
  • 别不必要地拷贝字符串
  • 运行期检查能改 assert 就改 assert

来源:第196期

2.2 编译器比你聪明,不要手动"优化"

编译器将代码转换为 IR,相同操作的不同实现会被转换为规范形式。多种计算加法的方式(循环、递归、复杂逻辑)都会编译为单个 ARM 指令 add w0, w1, w0。

常量乘法也一样:手动优化 522 为 (x << 9) + (x << 3) + (x << 1),编译器仍然会恢复为 imul。

优先考虑代码清晰性而不牺牲性能。

来源:第190期

2.3 __builtin_unreachable() 消除分支
cpp
uint8_t sum_with_constraints(const uint8_t *data, size_t len) {
if (len % 32 != 0) __builtin_unreachable(); // len 一定是32的倍数
if (len == 0) __builtin_unreachable(); // len 一定非零
return std::accumulate(data, data + len, uint8_t(0));
}

注意:把 data* 换成 vector,gcc 下可能不能优化。

来源:第180期

2.4 TLS 性能优化清单

thread_local 对象在有类构造函数 + -fPIC 共享库时需要额外调用 __tls_get_addr,成为性能瓶颈。

优化指南:

  • TLS 对象尽可能合并
  • 不要为 TLS 写构造函数(用 trivial 类型)
  • 频繁访问的对象用 __attribute__((visibility("hidden")))
  • 关键变量用 __attribute__((tls_model("initial-exec")))
  • 非共享库不要用 -fPIC
  • 考虑 -mtls-dialect=gnu2

来源:第180期

2.5 -O3 -flto 是免费午餐

Redis 测试:-O3 -flto 性能至少提升 5%。PGO(Profile-Guided Optimization)值得进一步研究。

来源:第100期

2.6 低延迟编程:减少分支和跳转
  • 勤用 && || 利用短路特性
  • 关注能生成 cmov 的写法(三元表达式、简单 if 赋值)
  • 减少虚函数使用(但 variant + visit 某些场景比虚函数好)
  • 善用 [[gnu::always_inline]] / __builtin_expect
  • 字符串比较的 if-else 链改 switch

来源:第150期

2.7 查表法替代除法/取模

除法指令很慢。整数转字符串(itoa)用查表法替代循环除 10:

cpp
static constexpr char radix_100_table[] = {
'0', '0', '0', '1', '0', '2', /* ... */
};
// 每次除100,查表取两位数字,速度翻倍

来源:第50期

2.8 SIMD 更节能

只要你的代码足够快,即使是 SIMD 这种费电的指令,整体能耗反而更少(因为执行时间短得多)。

来源:第150期

2.9 缓存友好的内存布局(SOA vs AOS)

AOS(Array of Structures)→ SOA(Structure of Arrays)转换可以显著提升缓存命中率,特别是在只访问部分字段时。

来源:第180期

2.10 循环优化:fission + interleave
  • Loop fission:拆分包含不同数据依赖的循环,降低数据 buffer 大小使其小于 L1 cacheline
  • Interleave:将不同任务交错分发,隐藏指令依赖链的延迟
  • 用 likwid 定位内存子系统瓶颈

来源:第150期


三、安全编码与 UB 避免

3.1 UB 的 43 条错觉(精选)

编译器的保证列表是空的。一旦有 UB,所有行为都是合规的:

  • UB 不只在 -O2/-O3 才触发
  • UB 的影响不局限于 UB 之后的代码 — UB 可以"时间旅行"
  • UB 不保证只是崩溃或死循环
  • 相同二进制 + 相同输入重复跑,行为不一定一样
  • 编译没报错不代表没有 UB
  • ODR 违规是编译期/链接期 UB

来源:第196期

3.2 有符号位移陷阱
cpp
// 64位机器上:
unsigned long set_bit_a(int bit) { return 1 << bit; } // 1 << 31 = 0xffffffff80000000 !!!
unsigned long set_bit_b(int bit) { return 1U << bit; } // 1U << 31 = 0x80000000 ✅

1 << 31 是有符号溢出(UB),符号扩展到 64 位时结果出乎意料。始终用 1U 或 1ULL。

来源:第150期

3.3 死循环也是 UB
cpp
int main() {
while(1) ; // 无副作用的死循环是 UB
}
void unreachable() {
std::cout << "hello world\n"; // clang 会打印这个!
}

编译器把无副作用的死循环优化掉,没有 ret,直接跳到下一个函数。

来源:第100期

3.4 整数溢出没有银弹

C++ 没有内建的溢出检查。现有方案:

  • 自定义类型加边界检查
  • Rust 风格的 overflowing_add / overflowing_mul
  • Chromium 的 checked math
  • -ftrapv 编译选项(性能损失大)

来源:第140期

3.5 浮点数比较
cpp
bool cmpEq(double a, double b,
double epsilon = 1e-7, double abstol = 1e-12) {
if (a == b) return true; // 处理 inf
double diff = std::fabs(a - b);
double reltol = std::max(std::fabs(a), std::fabs(b)) * epsilon;
return diff < reltol || diff < abstol;
}

或直接用 Boost.Test 的浮点比较实现。

来源:第100期

3.6 用 constexpr 在编译期捕获 UB

编译器在 constexpr 求值时必须拒绝 UB。可以利用这一点写编译期测试来捕获 UB。

来源:第150期

3.7 std::uintptr_t 处理地址

涉及地址转换时用 std::uintptr_t 而不是 uint32_t/uint64_t,避免 reinterpret_cast 的 -fpermissive 报错和平台兼容性问题。

来源:第150期


四、设计模式与惯用法

4.1 CRTP 表达式模板(延迟求值)

用于 Eigen 风格的数学库,避免中间临时对象:

cpp
template <typename E>
class VecExpression {
public:
double operator[](size_t i) const {
return static_cast<E const&>(*this)[i];
}
};
template <typename E1, typename E2>
class VecSum : public VecExpression<VecSum<E1, E2>> {
const E1& _u; const E2& _v;
public:
double operator[](size_t i) const { return _u[i] + _v[i]; }
};
// a + b + c 的类型是 VecSum<VecSum<Vec, Vec>, Vec>
// 赋值时才实际计算:elems[i] = a[i] + b[i] + c[i]

来源:第170期

4.2 防止对象切片
cpp
// C++20 方案:CRTP + concepts
template <typename T>
struct DontSlice {
DontSlice() = default;
DontSlice(const std::derived_from<T> auto&) = delete;
DontSlice& operator=(const std::derived_from<T> auto&) = delete;
DontSlice(std::derived_from<T> auto&&) = delete;
DontSlice& operator=(std::derived_from<T> auto&&) = delete;
};
struct Base : DontSlice<Base> {
int x_;
Base(int x) : x_(x) {}
using DontSlice<Base>::DontSlice;
};

来源:第190期

4.3 RAII scope_exit
cpp
template<class L>
class AtScopeExit {
L& m_lambda;
public:
AtScopeExit(L& action) : m_lambda(action) {}
~AtScopeExit() noexcept(false) { m_lambda(); }
};
// 使用宏简化
#define Auto(...) Auto_INTERNAL2(__COUNTER__, __VA_ARGS__)
// 用法
bool Mutate(State *state) {
state->DisableLogging();
Auto(state->EnableLogging());
if (!state->AttemptOperation1()) return false;
return true;
}

来源:第150期

4.4 std::variant 状态机
cpp
using State = std::variant<Idle, Running, Error>;
// 状态转换用 std::visit
State transition(State current, Event event) {
return std::visit(overloaded{
[](Idle, StartEvent) -> State { return Running{}; },
[](Running, ErrorEvent e) -> State { return Error{e.msg}; },
[](auto s, auto) -> State { return s; }, // 默认:保持不变
}, current, event);
}

来源:第120期

4.5 类型安全的字典(Tag Dispatch)
cpp
using dict = std::map<std::type_index, std::any>;
template <class Name, class T>
struct key final { explicit key() = default; };
template <class Name, class T>
auto get(const dict& d, key<Name, T> k) -> std::optional<T> {
if (auto pos = d.find(typeid(k)); pos != d.end())
return std::any_cast<T>(pos->second);
return std::nullopt;
}
// 声明 key(类只需声明不需定义)
using age_k = key<struct _age_, int>;
using name_k = key<struct _name_, std::string>;
constexpr inline auto age = age_k{};
constexpr inline auto name = name_k{};

注意:typeindex 计算较慢,大规模使用考虑字符串 hash 替代。

来源:第140期

4.6 transform_iterator 延迟计算
cpp
template <typename Iter, typename Func>
class transform_iterator {
Iter it; Func func;
public:
using value_type = std::invoke_result_t<Func,
typename std::iterator_traits<Iter>::value_type>;
transform_iterator& operator++() { ++it; return *this; }
value_type operator*() const { return func(*it); }
bool operator!=(const transform_iterator& o) const { return it != o.it; }
};
// 类似 range,延迟计算。C++20 有 views::transform 更好用

来源:第180期


五、并发与异步

5.1 C++20 协程最小实现

协程三要素:

  • Promise:存储异步状态和回调
  • Awaiter:实现 await_ready / await_suspend / await_resume
  • promise_type:通过 coroutine_traits 特化挂载协程语义
cpp
class Awaiter {
Promise& m_promise;
public:
bool await_ready() { return m_promise.IsReady(); }
void await_suspend(std::coroutine_handle<> handle) {
m_promise.AddCallback([handle]() { handle.resume(); });
}
void await_resume() {}
};

实际项目推荐用 Boost.Asio 或 cppcoro,不要自己造轮子。

来源:第196期

5.2 线程安全的编译期保证

用零开销 Token 类型在编译期保证只在主线程调用:

rust
pub struct MainThreadToken { _marker: PhantomData<*mut ()> }
// 需要 token 的函数签名
pub fn drain(&self, _token: MainThreadToken) { ... }

C++ 端用标记宏区分线程安全属性:

cpp
#define SYNC /* 线程安全的 const 方法 */
#define UNSYNC /* 线程不安全的 const 方法 */

来源:第195期

5.3 TLS 对象的析构顺序
  • thread_local 对象析构顺序不确定
  • 析构中访问已销毁的 TLS 对象是 UB
  • 非 trivial 的 TLS 对象在 -fPIC 下有额外性能开销

来源:第180期

5.4 锁内析构注意死锁

持有锁时销毁对象,如果对象的析构函数也需要加锁,就会死锁。特别注意 shared_ptr 的引用计数归零时机。

5.5 std::move 不保证移动

std::move 只是强制转换为右值引用:

  • 如果接收方没有移动构造函数,仍然会拷贝
  • const T&& 不会触发移动
  • 能返回值优化(RVO/NRVO)时不要 std::move

来源:第140期


六、编译器与工具链

6.1 编译时间分析
  • Clang:-ftime-trace 生成火焰图
  • GCC:配合 ClangBuildAnalyzer
  • Visual Studio 17.9+:内置编译时间分析、字段内存布局分析、include 分析
  • xmake:参考 xmake 的编译分析功能

来源:第150期

6.2 constinit 解决静态初始化顺序问题
cpp
constinit int global_value = 42; // 保证编译期初始化

避免 Static Initialization Order Fiasco。能用就用。

来源:第120期

6.3 Sanitizer 使用指南

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

  • SKILL.md in the repositoryCheckingSKILL.md

Popularity

Repository stars
549
Repository forks
29
7-day trend score
32

Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 23 May 2026, 5 months ago.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/wanghenshui/cppweeklynews/cppweeklynews/badge)](https://verified-skill.com/skills/wanghenshui/cppweeklynews/cppweeklynews)

Something wrong with this skill or its page? Tell us.