在这种情况下我应该使用新的吗?

时间:2011-12-28 00:23:18

标签: c++ memory

我有一张卡片,可以存储2个代表等级和套装的整数。我有一个类Deck,它包含存储在Array中的52个Card对象。当我初始化牌组时,我创建了所有52张牌并添加到牌组中。

当我这样做时,我应该使用

deck[i] = Card (rank, suit);

deck[i] = new Card (rank, suit);

为什么我要使用其中一个?

5 个答案:

答案 0 :(得分:5)

如果deckCard的数组,那么您需要第一个:deck[i] = Card (rank, suit);

如果deckCard*的数组,那么您需要第二个:deck[i] = new Card (rank, suit);

答案 1 :(得分:3)

因为一个有效,一个不是。

如果您的数组包含对象,

deck[i] = Card (rank, suit);

有效。

如果您的数组包含指向对象的指针,

deck[i] = new Card (rank, suit);

有效。

如果您尝试编译,您会发现其中一个错误。另一个是你想要的。

答案 2 :(得分:3)

如果您为每种情况适当地声明deck数组,则您建议的两个选项都有效。让我来讨论每个选项的好处:

deck[i] = Card (rank, suit);

  • 无需管理内存,因为所有分配都是隐式的并由编译器管理。使用指针需要更多的努力。
  • 假设Card类很简单,编译器生成的默认复制和赋值逻辑就足够了,你可以使用Card实例,就像它们是一个基本类型一样分配它们或将它们作为参数传递。
  • 通过仔细使用引用,您可以减少实例的复制,并最大限度地降低与此相关的性能损失。

deck[i] = new Card (rank, suit);

  • 每张卡片在游戏的整个生命周期中都是独一无二的。使用永不复制的独特卡片对游戏进行建模可能更容易。
  • 效率更高。将卡作为参数传递只是传递指针,无论每个Card实例有多大,同样用于在不同数组之间移动卡。与其他情况相比,按值移动Card实例需要将类的全部内容从内存中的一个位置复制到另一个位置。
  • 如果卡片是唯一且永远不会被复制,则可能更容易调试游戏状态。

在我看来,这两种方法都没有明显的优势,如果Card类如此之小,则更是如此。我可能会自己使用指针,但使用对象也不是一个糟糕的选择。

祝你好运。

答案 3 :(得分:2)

在这种情况下,使用Card数组或Card*数组有利有弊。   对于指针数组,您需要在删除数组之前手动删除每个指针(以防止内存泄漏)。这也会占用内存中非常小的空间。   作为一个优点,例如,交换两个卡很容易,因为你只需交换指针。   如果你有对象,要交换你需要修改它们或构造新对象(这可能很昂贵)。如果你选择指针,甲板也可以共享牌(我不知道为什么你会在这种特殊情况下使用它,但是为了普遍性而需要注意)。

如果你有一个对象数组,你不需要担心内存管理,但你会失去这种快速交换能力。

这取决于你评估哪一个更适合应用程序,但我个人认为你可以使用对象数组。

答案 4 :(得分:1)

如果您声明了一个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运算符,那么您实际上可以使用'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); 
}