如何通过命令模式核心逻辑实现系统撤销重做(UndoRedo)功能的源码编写?

2026-04-29 12:291阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1243个文字,预计阅读时间需要5分钟。

如何通过命令模式核心逻辑实现系统撤销重做(Undo/Redo)功能的源码编写?

由于默认底层是`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::stringQImage 副本,导致频繁编辑时内存暴涨。根本原因是没定义移动构造函数和移动赋值运算符,编译器默认生成拷贝版本。

阅读全文
标签:Cred

本文共计1243个文字,预计阅读时间需要5分钟。

如何通过命令模式核心逻辑实现系统撤销重做(Undo/Redo)功能的源码编写?

由于默认底层是`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::stringQImage 副本,导致频繁编辑时内存暴涨。根本原因是没定义移动构造函数和移动赋值运算符,编译器默认生成拷贝版本。

阅读全文
标签:Cred