C++ 纸牌游戏中的移动语义
我正在用C++ 纸牌游戏中的移动语义,c++,C++,我正在用C++编写纸牌后端。如果我不必怀疑某个东西是被复制还是被移动,生活会变得更容易,但是C++在这种情况下有什么意义呢?我只使用Python:d Anyhoo-我有一个Card对象,它遵守5的规则(它有一个构造函数、复制构造函数、复制赋值操作符、移动构造函数、移动赋值操作符)。我有不同的卡片分类 到目前为止,我一直在使用std::vector cards存储卡,每次我需要将卡从一个堆栈移动到另一个堆栈时,我都会: auto last_card = cards.back(); // Get t
C++
编写纸牌后端。如果我不必怀疑某个东西是被复制还是被移动,生活会变得更容易,但是C++
在这种情况下有什么意义呢?我只使用Python:d
Anyhoo-我有一个Card对象,它遵守5的规则(它有一个构造函数、复制构造函数、复制赋值操作符、移动构造函数、移动赋值操作符)。我有不同的卡片分类
到目前为止,我一直在使用std::vector 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
,这样我所做的只是复制/移动指针,而不是真正的对象吗
我正在寻找最佳实践,因为我对C++仍然是新的。如有任何提示/建议,将不胜感激
谢谢
编辑:为了澄清,
卡片
对象确实很简单。只是一套西装,价值和颜色(由西装推断)。所有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;
但是,这一切都是基于你对卡的描述而进行的模拟,这非常简单,而且不会从移动中获得任何好处。坦率地说,你可以复制一下,得到同样的结果。尽管如此,为将来变得更加复杂做好准备还是很好的。当然,这里没有什么东西需要独特的
这很好,除了几个细节:
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;
但是,这一切都是基于你对卡的描述而进行的模拟,这非常简单,而且不会从移动中获得任何好处。坦率地说,你可以复制一下,得到同样的结果。尽管如此,为将来变得更加复杂做好准备还是很好的。当然,这里没有任何东西需要一张唯一的\u ptr
你能告诉我为什么你使用移动
而不是只返回最后一张卡
?一些C++的最佳实践我不知道?没有看到你的代码>卡< /Cord>类,这是不可能说的。但我(表面上)的反应是这太复杂了;一张卡片只是几个值(suit和rank),特殊功能的默认版本可以正常工作。不必担心移动和复制,它们是一样的。通过移动返回通常是错误的。它可以抑制复制省略(这比移动更好)。是否卡包装任何资源(例如内存)?返回最后一张卡代码>是一个更好的解决方案。具有自动存储持续时间的局部变量在return
语句中被视为右值。您可能还需要auto last_card=std::move(cards.back())代码>,否则复制最后一个元素,然后立即销毁。您能告诉我为什么使用move
,而不只是返回last_card
?一些C++的最佳实践我不知道?没有看到你的代码>卡< /Cord>类,这是不可能说的。但我(表面上)的反应是这太复杂了;一张卡片只是几个值(suit和rank),特殊功能的默认版本可以正常工作。不必担心移动和复制,它们是一样的。通过移动返回通常是错误的。它可以抑制复制省略(这比移动要好)。卡是否包装任何资源(例如mem)