0

Barという別のクラスへのポインターのベクトルへのポインターであるメンバーを持つFooというクラスがあります。コンストラクタで初期化しますが、デストラクタで割り当てを解除する方法がわかりません。まだ勉強してる。あなたの助けをいただければ幸いです。このメンバーを持つ理由は、スコープがそのメソッドを超えて、つまりスタックを超えて存続するためです。ありがとう。

#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>>。これは完全に一致します(ただし、セルフクリーニング)。

于 2012-09-28T14:32:33.943 に答える
1

不適切な初期化と質問のタイトルから明らかなように、ポインタの数は少しばかげています。なぜなら、ポインタが行っているのは混乱とリークを引き起こしているからです。実際にはポインタはまったく必要ありません。また、クリーンアップについて心配する必要もありません。

コンストラクターに渡される最初の次元を持つ2D配列の場合、ベクトルのベクトルを使用できます。

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

渡されたサイズで外部ベクトルを初期化するには、イニシャライザーを使用します。

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

オブジェクトが破壊され、barsそのすべての要素も破壊されると、クリーンアップを忘れたり、不適切にクリーンアップしたりする可能性はありません。

パフォーマンスが問題になる場合、これは2D配列のように機能する一種のクラスに変換できますMatrix2Dが、実際には基礎となる1D配列しかありません。

于 2012-10-01T15:44:02.577 に答える
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配列と同じようにクラスを動作させる手法を使用しました。これは、演算子のオーバーロードと呼ばれます。これは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 に答える