我正在C++
中写一个纸牌后端。如果我不必怀疑是否要复制或移动某些内容,生活会更轻松,但是在这种情况下C++
的意义是什么?我只用Python:D。
Anyhoo-我有一个Card对象,它遵循5的规则(它有一个构造函数,Copy构造函数,Copy Assignment运算符,Move构造函数,Move Assignment运算符)。我为各种不同的卡牌设置了单独的课程。
到目前为止,我一直在使用std::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个都是枚举,并且还有其他辅助功能可用于翻转卡,检查卡面朝上还是朝下等。
答案 0 :(得分:4)
这很好,除了几个细节:
return std::move(last_card); // Move the card and return it.
这是一个常见的误解,您需要或应该这样做。在return
语句中,右边的东西自动是 xvalue ,因此它已经处于可移动状态。从这个意义上讲,std::move
在这里是多余的。
但是,这要比那差一点,因为编写std::move
会使编译器更加难以完全忽略甚至移动—仅编写return last_card
就可以得到想要的移动首先,甚至更好的是总避免了整个“爆炸”的总返回值选择。
现在,您当前有一份来自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
尖叫。