如何在Rust中结合#[cfg(...)]属性正确使用变量?
Rust Debug模式下条件断言的正确实现方式
你希望仅在Debug模式下运行断言相关代码,但当前写法在Release模式下会因找不到thing_initialized变量报错:
原错误代码
#[cfg(debug_assertions)] let mut thing_initialized = false; for ... { if cfg!(debug_assertions) { if expensive_check() { thing_initialized = true; } } } if cfg!(debug_assertions) { assert(thing_initialized); }
编译报错
error[E0425]: cannot find value `thing_initialized` in this scope
标准解决方案(无需过程宏或第三方库)
方法一:包裹完整逻辑到条件编译块
将涉及thing_initialized的变量声明、循环检查、断言全部放在#[cfg(debug_assertions)]块内,Release模式下整个代码块会被完全移除,彻底避免作用域问题:
#[cfg(debug_assertions)] { let mut thing_initialized = false; for ... { if expensive_check() { thing_initialized = true; } } assert!(thing_initialized); }
方法二:用闭包简化debug_assert!调用
利用debug_assert!本身仅在Debug模式生效的特性,把检查逻辑直接放到宏的条件闭包中,无需单独声明变量:
debug_assert!({ let mut initialized = false; for ... { if expensive_check() { initialized = true; } } initialized });
Release模式下,整个闭包会被编译器优化消除,不会产生任何运行时开销。
方法三:应急方案——声明哑变量(不推荐)
如果不想调整代码结构,可以在Release模式下声明一个无意义的哑变量,保证变量始终存在:
#[cfg(debug_assertions)] let mut thing_initialized = false; #[cfg(not(debug_assertions))] let thing_initialized = (); // Release模式下的哑变量,不会被实际使用 for ... { if cfg!(debug_assertions) { if expensive_check() { thing_initialized = true; } } } if cfg!(debug_assertions) { assert!(thing_initialized); }
这种方法代码冗余,仅适合临时兼容现有结构,优先推荐前两种方案。
内容的提问来源于stack exchange,提问作者Griffort
相关产品推荐
相关产品推荐

