动态切换算法的关键在于策略的内存管理与生命周期控制:必须用std::unique_ptr(或shared_ptr)替代裸指针,基类需声明virtual ~Strategy() = default;Qt中继承QObject时改用QScopedPointer;setStrategy应接收std::unique_ptr右值以确保所有权转移。

能动态切换算法,关键不在“怎么写接口”,而在于上下文如何持有策略、何时更换、以及内存生命周期是否可控——用 raw pointer 容易悬空,用 std::unique_ptr 是底线,std::shared_ptr 仅在跨作用域共享时才必要。
策略接口必须声明虚析构函数
否则通过基类指针 delete 派生对象会触发未定义行为,哪怕你暂时没显式 delete,只要用了 new 就必须防范。
- 错误写法:
class Strategy { public: virtual void execute() = 0; };—— 缺少virtual ~Strategy() = default; - 正确写法:所有策略基类第一行就该是
virtual ~Strategy() = default; - Qt 场景下如果继承自
QObject,则不能有虚析构(QObject 自带),此时必须用QScopedPointer或手动管理,不能用std::unique_ptr
上下文类里别裸存 raw pointer
裸指针 Strategy* 看似简单,但极易引发 dangling pointer:策略对象提前销毁,上下文还在调用 execute(),程序直接崩溃。
- 推荐用
std::unique_ptr<strategy></strategy>:所有权明确,自动释放,适合“上下文独占策略”的绝大多数场景 - 若策略需被多个上下文共享(如全局配置策略),改用
std::shared_ptr<strategy></strategy>,但要小心循环引用 - 绝对避免
Strategy* strategy_+new+ 忘记delete的组合,这是 C++ 策略模式最常见 crash 根源
setStrategy() 要处理所有权转移
用 std::unique_ptr 时,setStrategy() 不能只接收 Strategy*,否则无法接管内存;也不能直接接收 std::unique_ptr 值而不移动,否则编译失败。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
立即学习“C++免费学习笔记(深入)”;
- 正确签名:
void setStrategy(std::unique_ptr<strategy> new_strategy)</strategy> - 调用方式:
context.setStrategy(std::make_unique<quicksort>());</quicksort> - 若想支持栈上对象(如临时
MergeSort{}),需额外提供模板重载或接受std::shared_ptr,但会增加复杂度,一般不建议
模板策略可零成本但失去运行时灵活性
如果算法切换发生在编译期(比如模板参数决定排序方式),可用 template<typename strategy></typename> 实现零虚函数开销,但这时就不是“动态切换”了——它无法在用户输入后才决定用哪种排序。
- 运行时切换 → 必须用虚函数 + 智能指针
- 编译期选择 → 用模板 +
constexpr if(C++17)或概念(C++20),性能更好,但无法响应配置文件或 GUI 选项变化 - 混用风险:有人试图把模板策略塞进
std::unique_ptr<strategy></strategy>,结果因类型擦除失败而编译报错 —— 模板类和虚函数接口是两条路,不能强行合并
最容易被忽略的是策略对象的生存期是否比上下文更长;很多人测试时用全局策略对象或静态实例,上线后换成局部变量就崩——检查 every new 是否有对应 delete,或者直接绕过 new,全用 std::make_unique。

















