【问题标题】:Delete element from array of objects从对象数组中删除元素
【发布时间】:2020-01-31 12:40:42
【问题描述】:

我正在尝试处理 C++ 中的内存管理,所以我一直在编写一个纸牌游戏(它有一张纸牌列表),但没有使用 vector

假设我有一个 Cards 数组,如下所示:Card** cards。 现在,我想用另一张卡替换一张名为 Card* remove 的卡。

我认为我在cards 中的所有Card*s 都必须用new 创建,因为其他函数需要通过指针访问它们。因此,当我从cards 中删除一个元素时,我也应该delete 它。

但是,当我打电话给delete remove 时,它似乎弄乱了我的数组。具体来说,假设remove 恰好位于索引2。显然,在delete 之前,cards[2] == remove。但是,delete 之后,cards[2]remove 都发生了变化,而指向 cards 的指针是一样的。

这可能不是一件坏事,但我很困惑为什么会这样。理想情况下,我可以删除位于remove 的堆中的内存,而无需修改cards。我错过了什么?

【问题讨论】:

  • 您正在进行的练习或作业是关于指针和动态内存分配的吗?否则只需使用std::vector<Card>
  • 我对问题所在感到困惑;您不(或确实)认为应该改变的究竟是(或没有)改变?另外,当您删除remove 时,您会调用delete remove 还是delete cards[2]
  • 从指针数组中“删除”元素的一种简单方法是根本不删除元素,而是将指针设置为空指针(即cards[element_to_remove] = nullptr;)。否则,您可以创建一个少一个元素的新数组,并将剩余元素复制到新数组中。或者你可以在现有数组中将较高的元素向下复制一步。
  • @multitaskPro 那么你需要delete 是第一个当然。每个new 都应该匹配一个delete
  • 我想知道您是否在调试模式下运行,并且编译器已添加指令以将废话写入任何被删除的指针,因此从该点对该指针的任何访问都会失败,而不是只有在其他东西随机覆盖了那部分堆内存后才会失败。

标签: c++ pointers memory-management heap-memory


【解决方案1】:

我制作了一个示例代码来说明您所说的内容。但是我没有注意到你说的。
如果您可以显示您的代码(最小且可重现的示例),我们将能够找到发生了什么。

删除指针不会改变指针值,但会释放指针值

示例如下:

int main()
{
    typedef int Card;
    Card ** arr;

    // ---------- Init ----------
    arr = new Card* [5]; // five cards

    for(size_t i = 0; i < 5; ++i)
    {
        arr[i] = new Card(static_cast<int>(i));
    }
    // --------------------------

    // Direct removal
    std::cout << arr[2] << ": " << *arr[2] << '\n';
    delete arr[2];
    std::cout << arr[2] << '\n'; // >>>>> The address did not change after the deletion
    arr[2] = nullptr;

    std::cout << std::endl;

    // Delegated removal
    Card * to_remove = arr[3];
    std::cout << to_remove << " / " << arr[3] << " : " << *arr[3] << '\n';
    delete to_remove;
    std::cout << to_remove << " / " << arr[3] << '\n'; // >>>>> The address still did not change after deletion
    arr[3] = nullptr;

    // ----- Release memory -----
    for(size_t i = 0; i < 5; ++i)
        delete arr[i];

    delete[] arr;
    // --------------------------

    return 0;
}

输出:

0x2ea1c30: 2
0x2ea1c30

0x2ea5f40 / 0x2ea5f40 : 3
0x2ea5f40 / 0x2ea5f40

如您所见,指针值没有改变。


我认为重要的是要注意您应该将已删除的指针设置为nullptr,因为即使在删除之后它们仍在您的Card 列表中。

【讨论】:

  • 不幸的是,我刚刚发现了我的问题。您可以在我的问题上看到发生了什么的 cmets。我应该接受你的回答,回答我的解决方案,还是干脆删除我的问题?
  • @multitaskPro 对。似乎我花了太多时间来写我的答案:) 随意做你认为公平的事情,赞成,反对,接受或不接受,删除或不删除,或者什么都不做:)
猜你喜欢
  • 2017-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-12
  • 2018-03-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多