我应该在这种情况下使用新的吗?
我有一个类卡,存储代表等级和西装的2个整数。我有一个Deck类,其中包含52个存储在数组中的Card对象。当我初始化甲板时,我创建了所有52张牌,然后添加到甲板上。我应该在这种情况下使用新的吗?
当我这样做,我应该使用
deck[i] = Card (rank, suit);
或
deck[i] = new Card (rank, suit);
我为什么要使用一个或其他?
如果deck
是Card
一个数组,然后你想第一:deck[i] = Card (rank, suit);
如果deck
是Card*
一个数组,那么你希望第二个:deck[i] = new Card (rank, suit);
而在后一种情况下,你想_wrongly_。 – 2012-02-26 13:13:02
因为一个是有效的,一种是不。
如果数组包含对象,
deck[i] = Card (rank, suit);
是有效的。
如果数组包含对象的指针,
deck[i] = new Card (rank, suit);
是有效的。
如果你想编译,你会发现你的其中一个错误。另一个是你想要的。
在这种情况下,使用Card
的数组或Card*
的数组存在优点和缺点。 对于指针数组,您需要在删除数组之前手动删除每个指针(以防止内存泄漏)。这也会在内存中占用更多的空间。 作为一个优势,例如,交换两张卡片很容易,因为您只能交换指针。 如果你有对象,交换你需要修改它们或构建新的对象(这可能是昂贵的)。如果你选择了指针,套牌也可以共享卡片(我不知道你为什么会在这种特殊情况下使用这种卡片,但为了通用起见,这很有用)。
如果你有一个对象数组,你不需要担心内存管理,但是你会失去这种快速交换能力。
它取决于你评估哪一个更适合应用程序,但我个人认为你会很好的对象数组。
我回答了字面问题,但这可能是提问者正在寻找的东西。 – 2011-12-28 01:06:27
只要您为每种情况适当地声明deck
数组,您提出的两个选项都是有效的。让我讨论每个选项的好处:
deck[i] = Card (rank, suit);
- 无需管理内存,因为所有的分配是隐式由编译器管理。使用指针需要更多的努力。
- 假设
Card
类很简单,编译器生成的默认复制和赋值逻辑就足够了,您可以使用Card
实例,就好像它们是分配它们或将它们作为参数传递的基本类型一样。 - 通过仔细使用引用,您可能能够减少实例的复制并最大限度地降低与此相关的性能损失。
deck[i] = new Card (rank, suit);
- 每张卡是通过游戏的生命是独一无二的。使用独一无二的卡片来模拟游戏可能会更容易。
- 更高效。将卡作为参数传递只是传递一个指针,不管每个实例有多大,同样也适用于在不同数组之间移动卡。与另一种情况相比,按值移动
Card
实例需要将类的全部内容从内存中的一个位置复制到另一个位置。 - 如果卡片是唯一的并且从不复制,则可能更容易调试游戏的状态。
在我看来,这两种方法都没有明显的优势,如果Card
的课程太小,更是如此。我可能会自己用指针,但使用对象也不是一个坏的选择。
祝你好运。
如果声明的Card
项的数组,那么项目将默认构造当数组分配,然后你必须回去以后更新个人Card
项目与他们的新值,例如:
Card deck[52];
for (int i = 0; i < 52; ++i)
{
rank = ...;
suit = ...;
deck[i] = Card(rank, suit);
// better, add a method to the `Card` class to
// update the values without constructing any
// temporary instances at all...
//
// deck[i].set(rank, suit);
}
如果声明的Card
指针数组,那么你可以使用你的Card
构造所需值初始化每个Card
项目,但在每个Card
项目分配一个单独的内存块的成本,如:
Card* deck[52];
for (int i = 0; i < 52; ++i)
{
rank = ...;
suit = ...;
deck[i] = new Card(rank, suit);
}
您可以将二者结合起来,如果你使用std::vector
不是数组,例如:
std::vector<Card> deck(52);
for (int i = 0; i < 52; ++i)
{
rank = ...;
suit = ...;
deck[i] = Card(rank, suit);
// or:
// deck[i].set(rank, suit);
}
如果使用placement new
操作,那么实际上你可以利用“新”运营商打电话给你Card
构造,而不用于每个Card
分配一个单独的存储块,而不必为默认构建体,然后分别复制分配Card
值,例如:
unsigned char deck_buffer[sizeof(Card) * 52];
Card *deck = (Card*) deck_buffer;
for (int i = 0; i < 52; ++i)
{
rank = ...;
suit = ...;
new (&deck[i]) Card(rank, suit);
}
内存管理在C++中是一件复杂的事情。人们写关于它的书籍。你应该阅读它们。 – 2011-12-28 00:25:45