如何清理指向类的指针向量的指针的类成员?

时间:2012-09-28 14:20:58

标签: c++

我有一个名为Foo的类,它有一个成员,指向另一个名为Bar的类的指针向量。我在构造函数中初始化它但我不确定如何在析构函数中释放它。我还在学习。非常感谢你的帮助。拥有此成员的原因是范围超出该方法,即超出堆栈。感谢。

#include <iostream>
#include <vector>

using namespace std;

class Bar {};

class Foo {
public:
    Foo() {
        bars = new vector<Bar*>*[10];

        for (int i = 0; i < 10; i++) {
            bars[i]->push_back(new Bar());
        }
    }

    ~Foo () {
        for (int i = 0; i < 10; i++) {
            // TODO: how to clean up bars properly?
        }
    }

private:
    vector<Bar*>** bars;
};

int main () {
    new Foo();
    return 0;
}

更新:我感谢所有方面的反馈。我是C和C ++的新手。基本上我想要一个2d结构作为类成员,它将在类的生命周期中持续存在。外部结构是阵列的原因是因为我知道它需要多大。否则我以前使用矢量矢量。

5 个答案:

答案 0 :(得分:2)

甚至没有正确分配。您为std::vector<Bar*>分配了一组指针,但从未分配任何std::Vector<Bar*>

最好的办法就是std::vector<std::unique_ptr<Bar>>甚至std::unique_ptr<std::vector<std::unique_ptr<Bar>>>之类的东西。你得到的只是WTF。

std::unique_ptr<std::array<std::unique_ptr<std::vector<std::unique_ptr<Bar>>>, 10>>。这是完全匹配(但是自我清理)。

答案 1 :(得分:1)

指针的数量有点荒谬,因为他们所做的只是导致混乱和泄漏,从非正确的初始化和问题的标题可以看出。你根本不需要任何指针,也不必担心任何清理。

对于第一维传递到构造函数的2D数组,可以使用向量向量:

std::vector<std::vector<Bar>> bars; 

要使用传入的大小初始化外部向量,请使用初始值设定项:

Foo(size_t size) 
    : bars(size) {}

当对象被销毁时,bars及其所有元素也是如此,因此没有机会忘记清理或不正确地进行清理。

如果性能是一个问题,可以将其转换为一种Matrix2D类,其作用类似于2D数组,但实际上只有一个基础的一维数组。

答案 2 :(得分:0)

编辑:在2D结构的情况下(并且你说你知道你的2D结构需要多大,所以我们假设你的循环中的10是你想要的2D数组的大小。

#include <iostream>
#include <vector>

using namespace std;

class Bar {
public:
    int BarInfo;
};

class Foo {
public:
    Foo() {
        // Allocates 10 vector spots for 10 bar elements - 100 bars, 10 x 10
        for (int i = 0; i < 10; i++) {
            // Puts 10 bars pointer at the end;
            // Heap-allocated (dynamically), which
            // means it survives until you delete it
            // The [10] is array syntax, meaning you'll have 10 bars
            // for each bars[index] and then
            // you can access it by bars[index][0-9]
            // If you need it to be more dynamic
            // then you should try vector<vector<Bar>>
            bars.push_back(new Bar[10]);
        }
    }

    Bar* operator[] (int index) {
        return bars[index];
    }

    ~Foo () {
        // Cleanup, because you have pointers inside the vector,
        // Must be done one at a time for each element
        for (int i = 0; i < bars.size(); i++) {
            // TODO: how to clean up bars properly?
            // Each spot in the vector<> contains 10 bars,
            // so you use the array deletion
            // and not just regular 'delete'
            delete[] bars[i]; // deletes the 10 array elements
        }
    }

private:
    // vector might not be a bad idea.
    vector<Bar*> bars;
};

这是我测试编写的代码的主要内容,它就像你认为2D数组应该有效一样:

int main ( int argc, char* argv[] ) {
    Foo foo;
    // Bar at 1st row, 2nd column ( row index 0, column index 1 )
    // Bar& is a reference
    Bar& bar12 = foo[0][1];
    bar12.BarInfo = 25;
    int stuffInsideBar = foo[0][1].BarInfo; // 25
    return 0;
}

我希望这有助于让你更接近你正在做的事情。我在这里使用了一种技术,可能会超过一个初学者头,使Foo类的行为与您认为的2D数组一样。它被称为operator overloading。它是C ++中的一个强大功能,因此一旦掌握了更多基础知识,它可能对您未来的项目或当前项目有用。祝好运!

~~~~~~~~~~~~~~~~~~~~~~~

编辑前的旧答案

~~~~~~~~~~~~~~~~~~~~~~~

看起来你做的间接太多了。虽然另一个人的答案告诉你如何清理你已经设法做的事情,但我认为你可以从改变你正在处理课程的方式中受益。

#include <iostream>
#include <vector>

using namespace std;

class Bar {};

class Foo {
public:
    Foo() : bars() {
        // bars is no longer a pointer-to-vectors, so you can just
        // allocate it in the constructor - see bars() after Foo()
        //bars = new vector<Bar>();

        for (int i = 0; i < 10; i++) {
            // Puts 1 bar pointer at the end;
            // Heap-allocated (dynamically), which
            // means it survives until you delete it
            bars.push_back(new Bar());
        }
    }

    ~Foo () {
        // Cleanup, because you have pointers inside the vector,
        // Must be done one at a time for each element
        for (int i = 0; i < 10; i++) {
            // TODO: how to clean up bars properly?
            // TODOING: One at a time
            delete bars[i]; // deletes pointer at i
        }
    }

private:
    // You don't need to ** the vector<>,
    // because it's inside the class and 
    // will survive for as long as the class does
    // This vector will also be copied to copies of Foo,
    // but the pointers will remain the same at the time
    // of copying.
    // Keep in mind, if you want to share the vector, than
    // making it a std::shared_ptr of a
    // vector might not be a bad idea.
    vector<Bar*> bars;
};

如果您通过引用将类传递给函数,那么类中的vector<Bar*>将不会复制自身或删除自身,使其保持在单个堆栈帧之后。

main中,这应该正确清理,并且比矢量**更容易跟踪。但是,如果出于某种原因需要vector **,那么home_monkey的答案应该会对你有所帮助。

答案 3 :(得分:-1)

我认为分配存在问题。这条线

new vector <Bar*> * [10] 

将为您提供一系列指向vector <Bar*> *类型的对象的点数 需要为vector <Bar*>类型分配一些额外的内存。

我已经去了,

Foo() 
{
    bars = new vector<Bar*>*[10]; // A.

    for (int i = 0; i < 10; i++) 
    {
        bars[i] = new vector<Bar*>;  //  B. Extra memory assigned here.
        bars[i]->push_back(new Bar); //  C.
    }
}

要释放资源,您必须撤消上述

~Foo () 
{
    for (int i = 0; i < 10; i++) 
    {
        //  I'm assuming that each vector has one element
        delete bars[i][0]; //  Free C 
        delete bars[i];    //  Free B    
    }

    delete [] bars; // Free A
}

答案 4 :(得分:-2)

我不相信你甚至正确地分配它。要撤消你到目前为止所做的事情,你所要做的就是:

for(int i=0; i < 10; ++i)
    while(bars[i]->size > 0)
    {
        delete *bars[i]->front();
        pop_front();
    }
delete[] bars;

但是,你需要自己分配每个向量,例如在构造函数中:

for(int i=0; i<10; ++i)
    bars[i] = new vector<Bar*>();

这需要您将析构函数更改为:

for(int i=0; i < 10; ++i)
{
    while(bars[i]->size > 0)
    {
        delete *bars[i]->front();
        pop_front();
    }
    delete bars[i];
}
delete[] bars;

关于您的更新,我建议您将条形类型更改为:

vector<Bar*>* bars;

和分配到(不需要进行上面建议的for循环分配):

bars = new vector<Bar*>[10];