如何通过命令模式核心逻辑实现系统撤销重做(UndoRedo)功能的源码编写?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1243个文字,预计阅读时间需要5分钟。
由于默认底层是`std::deque`,不支持迭代器遍历、无法随机访问历史节点,也无法在中间插入或回滚到任意位置——而实际编辑场景常需跳转到第5步或重复时跳过某条命令——因此,`std::stack`的`top()`返回的是const引用,无法安全地移动资源(如移动独占型命令对象)。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 改用
std::vector<:unique_ptr>></:unique_ptr>存储命令序列,保留索引位置和可遍历性 - 维护一个
m_currentIndex指向「当前已执行的最后一条命令」,初始为 -1(表示无任何执行) - Undo 时不是 pop,而是调用
command->undo()并递减索引;Redo 是递增索引后调用command->redo() - 新命令追加前,先清空
m_redoStack(即从m_currentIndex + 1到末尾的所有命令)
Command 基类必须支持 move semantics 才能避免深拷贝开销
很多初版实现把命令数据全量拷贝进 Command 对象,比如存一份 std::string 或 QImage 副本,导致频繁编辑时内存暴涨。根本原因是没定义移动构造函数和移动赋值运算符,编译器默认生成拷贝版本。
本文共计1243个文字,预计阅读时间需要5分钟。
由于默认底层是`std::deque`,不支持迭代器遍历、无法随机访问历史节点,也无法在中间插入或回滚到任意位置——而实际编辑场景常需跳转到第5步或重复时跳过某条命令——因此,`std::stack`的`top()`返回的是const引用,无法安全地移动资源(如移动独占型命令对象)。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 改用
std::vector<:unique_ptr>></:unique_ptr>存储命令序列,保留索引位置和可遍历性 - 维护一个
m_currentIndex指向「当前已执行的最后一条命令」,初始为 -1(表示无任何执行) - Undo 时不是 pop,而是调用
command->undo()并递减索引;Redo 是递增索引后调用command->redo() - 新命令追加前,先清空
m_redoStack(即从m_currentIndex + 1到末尾的所有命令)
Command 基类必须支持 move semantics 才能避免深拷贝开销
很多初版实现把命令数据全量拷贝进 Command 对象,比如存一份 std::string 或 QImage 副本,导致频繁编辑时内存暴涨。根本原因是没定义移动构造函数和移动赋值运算符,编译器默认生成拷贝版本。

