0

我有一个名为 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 结构作为类成员,它会在类的生命周期内持续存在。外部结构是数组的原因是因为我知道它需要多大。否则我以前使用向量的向量。

4

5 回答 5

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>>.This 完全匹配(但自清洁)。

于 2012-09-28T14:32:33.943 回答
1

指针的数量有点荒谬,因为它们所做的只是造成混乱和泄漏,这从不正确的初始化和问题的标题中可以看出。您实际上根本不需要任何指针,也不必担心任何清理工作。

对于将第一个维度传递给构造函数的二维数组,您可以使用向量的向量:

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

要使用传入的大小初始化外部向量,请使用初始化程序:

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

当对象被销毁时,bars它的所有元素也被销毁,因此不会忘记清理或清理不当。

如果性能是一个问题,这可以转换为一种Matrix2D类似于二维数组的类,但实际上只有一个底层的一维数组。

于 2012-10-01T15:44:02.577 回答
0

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

#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;
};

这是我用于测试编写的代码的主要方法,它的工作方式就像你认为二维数组应该工作一样:

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 数组一样。这称为运算符重载。它是 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 的答案应该可以帮助您更多。

于 2012-09-28T14:51:24.887 回答
-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
}
于 2012-09-28T14:44:15.350 回答
-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];
于 2012-09-28T14:23:42.930 回答