8

私が遭遇している問題のために、ポインターのベクトルを作成することは可能ですか?もしそうなら、どのように?特にイテレータと.begin()の使用に関しては、次のようになります。このベクトルをポインタのベクトルに変換するにはどうすればよいですか。

class c
{
     void virtual func();
};

class sc:public c
{
     void func(){cout<<"using func";}
};

sc cobj;

vector<c>cvect
cvect.push_back(cobj);
vector<c>::iterator citer

for(citer=cvect.begin();citer<cvect.end();citer++)
{
     citer->func();
}
4

6 に答える 6

17

もちろん。

vector<c*> cvect;
cvect.push_back(new sc);
vector<c*>::iterator citer;
for(citer=cvect.begin(); citer != cvect.end(); citer++) {
  (*citer)->func();
}

覚えておくべきこと:

私の例で行ったように動的に割り当てられたメモリを使用する場合は、自分自身の後でクリーンアップする必要があります

例えば:

 for(...) { delete *i; }

これは、sのベクトルshared_ptr(のようなboost::shared_ptr)を使用することで簡略化できます。これに使用しようとしないでくださいstd::auto_ptr、それは機能しません(コンパイルさえしません)。

もう1つ覚えておくべきことは<、可能な場合はループ内のイテレータの比較に使用しないようにする必要があります。これは、ランダムアクセスイテレータをモデル化するイテレータでのみ機能します。つまり、コードを変更して使用することはできませんstd::list

于 2009-05-03T15:08:48.413 に答える
9

vector <c> cvectポインタのベクトルではありません。これは、タイプcのオブジェクトのベクトルです。あなたが欲しいvector <c*> cvect。そしてあなたはおそらく望むでしょう:

cvect.push_back( new c );

そして、イテレータが与えられた場合、次のようなものが必要になります。

(*it)->func();

もちろん、そもそもポインタのベクトルが欲しくない可能性はかなりあります...

于 2009-05-03T15:01:15.560 に答える
4

はい、可能です。実際、ベクターに単一の型ではなくクラス階層全体のオブジェクトを含める場合は、ポインターを使用する必要があります。(ポインターを使用しないと、オブジェクトのスライスという恐ろしい問題が発生します。すべてのオブジェクトはサイレントに基本クラス型に変換されます。これはコンパイラーによって診断されず、ほぼ確実に必要なものではありません。)

class c
{
     void virtual func();
};

class sc:public c
{
     void func(){cout<<"using func";}
};

sc cobj;

vector<c*> cvect;             // Note the type is "c*"
cvect.push_back(&cobj);       // Note the "&"
vector<c*>::iterator citer;

for(citer=cvect.begin();citer != cvect.end();citer++)   // Use "!=" not "<"
{
     (*citer)->func();
}

ポインタのベクトルでは、独自のメモリ管理を行う必要があることに注意してください。したがって、非常に注意してください。ローカルオブジェクトを使用する場合(上記のように)、コンテナが使用する前にスコープから外れてはなりません。で作成されたオブジェクトへのポインタを使用する場合は、コンテナを破棄する前に手動でポインタを使用newする必要があります。deleteこの場合、smart_ptrによって提供されるようなスマートポインタの使用を絶対に検討する必要がありBoostます。

于 2009-05-03T15:10:15.820 に答える
2

vector<c*>ポインタのベクトルを作成しました。次に、を使用newしてcオブジェクトにメモリを割り当て、それらをベクターにプッシュします。deleteまた、自分自身が必要であり、vector.clear()がcオブジェクトに割り当てられたメモリを解放しないことを忘れないでください。ここでは、cをポインタのベクトルとして格納する必要があります。そうしないと、仮想関数の呼び出しが機能しません。

于 2009-05-03T15:03:00.707 に答える
2

はい、確かに。

// TestCPP.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <vector>


using namespace std;

class c
{
public:
    void virtual func() = 0;
};

class sc:public c
{
public:
    void func(){cout<<"using func";}
};

int _tmain(int argc, _TCHAR* argv[])
{
    sc cobj;

    vector<c*> cvect;
    cvect.push_back(&cobj);
    vector<c*>::iterator citer;

    for(citer=cvect.begin();citer<cvect.end();citer++)
    {
        (*citer)->func();
    }

    return 0;
}

vector<c*> cvectの宣言と使用に注意してくださいcvect.push_back(&cobj)

提供されたコードから、イテレータを間違った方法で使用しています。イテレータが指しているメンバーにアクセスするには、単独では*citerなく使用する必要があります。citer

于 2009-05-03T15:07:52.627 に答える
0

Boost Pointer Container Libraryを試してみてください。次のような、通常のポインターのベクトルに比べていくつかの利点があります。

my_container.push_back( 0 );            // throws bad_ptr 
ptr_vector<X> pvec; 
std::vector<X*> vec;
( *vec.begin() )->foo(); // call X::foo(), a bit clumsy
pvec.begin()->foo();     // no indirection needed
于 2009-05-04T22:10:31.027 に答える