c++ - 在纸牌游戏中移动语义
问题描述
我正在写一个纸牌后端C++
。如果我不必怀疑某些东西是否被复制或移动,生活会更轻松,但C++
在这种情况下有什么意义呢?我只会使用 Python :D。
Anyhoo - 我有一个遵守规则 5 的 Card 对象(它有一个构造函数、复制构造函数、复制赋值运算符、移动构造函数、移动赋值运算符)。我为各种卡片组设置了单独的课程。
到目前为止,我一直在使用 astd::vector<Card> cards
来存储卡片,每次我需要将卡片从一个堆栈移动到另一个堆栈时,我都会这样做:
auto last_card = cards.back(); // Get the last element in the collection.
cards.pop_back(); // Remove the last element.
return std::move(last_card); // Move the card and return it.
我的问题是 - 这是正确的方法吗?我是否应该改为使用一个std::vector<std::unique_ptr>
,以便我所做的只是复制/移动指针而不是真实对象?
我正在寻找最佳实践,因为我还是 C++ 新手。任何提示/建议将不胜感激。
谢谢!
编辑:澄清一下,Card
对象真的很简单。只是一套西装,价值和颜色(由西装推断)。所有 3 个都是枚举,并且还有额外的辅助函数用于翻转卡片、检查卡片是正面朝上还是朝下等。
解决方案
这非常好,除了几个细节:
return std::move(last_card); // Move the card and return it.
您需要或应该这样做是一个常见的误解。在一个return
语句中,右边的东西自动是一个xvalue,因此它已经处于可移动状态。从这个意义上说,std::move
那里是多余的。
但它比这更糟一点,因为通过编写std::move
,您使编译器更难完全忽略甚至移动 - 通过编写return last_card
,您将首先获得您想要的移动,甚至更好的总返回值省略,避免整个shebang。
现在,目前您有一份来自cards.back()
; 该cards.back()
表达式在那里不是右值,因为它是对其他地方存在的东西的引用,这基本上是一个左值!所以你可能想做:
auto last_card = std::move(cards.back());
另外,我只是想提醒您注意“移动卡片并返回它”的观察:记住,std::move
不会移动任何东西,它只是给您一个指代事物的右值表达式。如果发生移动,它将在返回操作中,而不是在它之前。
总之,我的建议:
// Extract the last element in the collection
auto last_card = std::move(cards.back());
// Remove the now-dead last element
cards.pop_back();
// Return the new card (will automatically be moved if elision doesn't occur)
return last_card;
但是,根据您对 的描述,这一切都没有实际意义Card
,这非常简单,并且不会从移动中获得任何好处。坦率地说,您可以复制它并获得相同的结果。尽管如此,为它在未来变得更加复杂做好准备是件好事。当然,这里没有什么值得尖叫的unique_ptr
。
推荐阅读
- c++ - 如何使用 ffmpeg 获得正确的帧持续时间?
- bash - 如何使用 bash 脚本使用密码自动 ssh 进入服务器和 su?
- php - 如何使用php重定向页面
- html - 如何在 Angular 中控制单个 HTML 项?
- git - git:获取另一个分支失败
- json - 将 json 响应转换为字符串并将其放入结构中
- html - 如何使文本适合所有 div 的宽度?
- ios - 尝试在 UIImageView 中的图像之间淡入淡出时出现白屏
- node.js - Swagger - 无法读取未定义的属性“获取”
- ios - 架构 x86_64 的未定义符号 - 我可以在设备上构建和运行,但不适用于模拟器