释放指针数组的内存?

时间:2012-02-04 19:35:50

标签: arrays pointers visual-c++ dynamic delete-operator

我有Deck和PlayingCard课程。 Deck对象必须具有动态分配的指向PlayingCard对象的指针数组:

PlayingCard** _playing_cards;

要初始化此数组,将调用Deck的构造函数和build()函数:

Deck::Deck(int size)
{
    _total_playing_cards = size;
    _deal_next = 0;
    build();
}

void Deck::build()
{
    _playing_cards = new PlayingCard*[_total_playing_cards];
    for(int i = 1; i <= _total_playing_cards; ++i)
    {
        _playing_cards[i-1] = new PlayingCard(i % 13, i % 4);
    }
}

释放使用'new'分配的内存在析构函数中处理:

Deck::~Deck()
{
    for(int i = 0; i < _total_playing_cards; ++i)
    {
        delete[] _playing_cards[i];
    }
    delete[] _playing_cards;
}

然后我有一个单独的文件,deck_test.cpp,它有一个main()来简单地构造和破坏Deck对象:

int main()
{
    Deck deck(52);
    deck.~Deck();
    return 0;
}

这编译很好,但在调试时,Visual Studio在Play Cards.exe中报告“0x5ab159da(msvcr100d.dll)的未处理异常:0xC0000005:访问冲突读取位置0xfeeefee2。”在查看调用堆栈时,问题似乎发生在我在析构函数中的'for'循环中使用'delete []'运算符的地方。这不是从指针数组中释放内存的正确方法吗?

4 个答案:

答案 0 :(得分:2)

你的Deck析构函数需要阅读如下:

Deck::~Deck()
{
    for(int i = 0; i < _total_playing_cards; ++i)
    {
        delete _playing_cards[i];
    }
    delete[] _playing_cards;
}

请注意,在循环中,您必须使用非数组删除来删除单个扑克牌。

还有另一个更大的问题,即你正在调用析构函数两次 - 一次是在你的显式调用中,第二次是当deck在main()结束时超出范围。基本上你不应该在C ++中手动调用非堆分配对象上的析构函数,因为你干扰了C ++对象的内置生命周期管理。不好的想法,除非你(a)真的知道你在做什么,(b)你是在非常具体的情况下做的。

顺便说一句,除非你正在学习指针并尝试使用指针,否则使用动态分配的指针数组会带来所有开销。在生产代码中,请自己和其他人一个忙,并使用std :: vector代替。

答案 1 :(得分:1)

请不要直接在main()中调用析构函数。

稍微修改析构函数代码:

Deck::~Deck()
{
    if (_playing_cards) {
        for (std::size_t i = 0; i < _total_playing_cards; ++i) {
            delete _playing_cards[i];
            _playing_cards[i] = NULL;
        }
        delete[] _playing_cards;
        _playing_cards = NULL;
    }
}

顺便说一下,为什么不使用std::vector<PlayingCard>

答案 2 :(得分:0)

这是因为两件事:

  1. 手动调用析构函数,然后在变量超出范围时再次调用析构函数。你通常不应该手动调用析构函数,除非对象是使用展示位置new分配的,或者在它超出范围之前偷偷重建具有展示位置new的对象(但不要这样做)

  2. delete[] _playing_cards[i];应为delete _playing_cards[i],因为playing_cards[i]不是数组,只是new PlayingCard

  3. 另外,为什么你在一个地方i = 1; i <= _total_playing_cards和另一个地方i = 0; i < _total_playing_cards?它不必要地使事情变得复杂,我建议选择一个(最好是后者)并坚持下去。

答案 3 :(得分:0)

你不必打电话给甲板.~甲板();靠自己。它会自动调用。只需使用:

int main()
{
    Deck deck(52);
    return 0;
}

并在for循环中使用delete _playing_cards[i];,因为delete[]表示删除数组,而delete表示只删除一个元素。