【问题标题】:Deleting an Array of Pointers - Am I doing it right?删除指针数组 - 我做对了吗?
【发布时间】:2011-03-24 18:36:02
【问题描述】:

我觉得提出关于删除指针的问题有点愚蠢,但我需要确保我以正确的方式删除,因为我目前正在调试我的程序。

基本上我有几个指针数组,它们在我的头文件中定义如下:

AsteroidView *_asteroidView[16];

然后在 for 循环中初始化它们:

for(int i = 0; i < 16; i++)  
{  
      _asteroidView[i] = new AsteroidView();  
} 

好的,到目前为止一切顺利,一切正常。 当我最终需要在析构函数中删除这些时,我使用以下代码:

for(int i = 0; i < 16; i++)  
{  
        delete _asteroidView[i];  
}

这就是我需要做的一切吗?我觉得是这样,但我担心会出现内存泄漏。

出于兴趣... 点到对象的数组和对象的数组有很大区别吗?

【问题讨论】:

  • 是的,这很好 - 你不会泄漏内存。
  • 考虑使用智能指针数组,这样就不需要在析构函数中编写循环。
  • 不要在全局范围内声明带有前导下划线的变量(这些标识符是为实现保留的)。该实现不太可能使用标识符 _asteroidView,但您现在应该改掉这是一个坏习惯。
  • 它可以工作(虽然不是异常安全的)。但真正的问题是您是否需要动态分配 AsteroidView?如果没有更多上下文,很难判断这是否(或@Space_V0wb0y 解决方案是最好的)。
  • Martin,它们是私有的,而不是全局变量……抱歉,我在帖子中没有说清楚。老实说,我可能不需要动态分配它......

标签: c++ arrays pointers delete-operator


【解决方案1】:

这是正确的。不过,您不妨考虑使用Boost.PointerContainer,省去手动管理资源的麻烦:

boost::ptr_vector<AsteroidView> _asteroidView;
for(int i = 0; i < 16; i++)
{
    _asteroidView.push_back(new AsteroidView());
}

您不必管理删除,容器会为您完成。这种技术被称为RAII,如果你想用 C++ 玩得开心,你应该学习它:)

关于您的编辑:有几个不同之处,但我想最重要的是这些:

  1. 指针数组可以包含不同类型的对象,前提是这些对象是数组类型的子类。
  2. 对象数组不需要任何删除,数组销毁时所有对象都被销毁。

【讨论】:

  • +1 用于托管解除分配。他也可以考虑简单地使用std::vector 或boost::scoped_array
  • 感谢您的帮助,很高兴我做得对。将研究 Boost。
  • @AJG85 本来打算使用 std::vector 但一直没有时间改变一切。在我确定一切正常后可能会更改它。
【解决方案2】:

没问题。

经验法则是:将每次调用new 与适当调用delete 匹配(每次调用new[] 与调用delete[])

【讨论】:

  • 谢谢!我不确定最后是否需要一个额外的 delete[],因为它是一个数组。很高兴我做对了,谢谢你的帮助:)
  • 只有当您使用 new[] 分配数组本身时,您才需要 delete[] - 所以一切都很好。
【解决方案3】:

这就是我需要做的一切吗?我觉得是这样,但我担心会出现内存泄漏。

是的。该程序正在正确地释放资源。没有内存泄漏:)


如果您对使用std::vector(事实上它很容易)感到满意,它会在超出范围时执行释放过程。但是,类型应该是 -

std::vector<AsteroidView>

【讨论】:

    【解决方案4】:

    给定一个类:

    // this class has hidden data and no methods other than the constructor/destructor
    // obviously it's not ready for prime time
    class Foo {
        int* bar_[16];
    
        public:
        Foo()
        {
            for (unsigned int i = 0; i < 16; ++i)
                bar_[i] = new int;
        }
    
        ~Foo()
        {
            for (unsigned int i= 0; i < 16; ++i)
                delete bar_[i];
        }
    };
    

    如果构造函数正确完成,您将不会泄漏内存。但是,如果 new 在构造函数中失败(如果内存不足,new 会抛出 std::bad_alloc),then the destructor is not run,你将有内存泄漏。如果这让您感到困扰,您将不得不使构造函数异常安全(例如,在构造函数周围添加一个 try ... catch 块,使用 RAII)。就个人而言,如果数组中的元素必须是指针,我只会使用 Boost Pointer Container,如果不是,我会使用 std::vector。

    【讨论】:

    • 我猜元素不一定是指针......我不太确定为什么我一开始就那样做。抱歉,我确实有 try catch,我只是认为没有必要将它们包含在帖子中。
    • 这只是您需要注意的事情。这些项目是指针的主要原因是如果AsteroidView 是一个基类并且容器可以保存从AsteroidView 派生的对象。
    猜你喜欢
    • 2015-08-09
    • 1970-01-01
    • 1970-01-01
    • 2013-04-22
    • 2011-05-10
    • 1970-01-01
    • 2015-07-15
    • 1970-01-01
    相关资源
    最近更新 更多