ポインターのベクトルを作成することは可能ですか?
-
03-07-2019 - |
質問
ただ、疑問に思っているのは、私が直面している問題のために、ポインターのベクトルを作成することは可能ですか?もしそうなら、どのように?具体的には、イテレータと.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();
}
解決 2
vector <c> cvect
は、ポインターのベクトルではありません。タイプcのオブジェクトのベクトルです。 vector <c*> cvect
が必要です。そしておそらくあなたが望む:
cvect.push_back( new c );
そして、イテレータを指定すると、次のようなものが必要になります:
(*it)->func();
もちろん、そもそもポインターのベクトルが必要ではなかった可能性が高いです...
他のヒント
もちろん。
vector<c*> cvect;
cvect.push_back(new sc);
vector<c*>::iterator citer;
for(citer=cvect.begin(); citer != cvect.end(); citer++) {
(*citer)->func();
}
留意事項:
この例で行ったように動的に割り当てられたメモリを使用する場合は、自分の後にクリーンアップする必要があります
e.g。:
for(...) { delete *i; }
これは、shared_ptr
sのベクトル(boost::shared_ptr
など)を使用して単純化できます。これにはstd::auto_ptr
を使用しないでください。機能しません(コンパイルすらしません)。
覚えておくべきもう1つのことは、ループ内のイテレーターを比較するために可能な限り<
を使用しないでください。ランダムアクセスイテレーターをモデル化するイテレーターに対してのみ機能します。つまり、コードを使用例std::list
。
はい、可能です。実際、単一の型ではなくクラス階層全体のオブジェクトをベクターに含める場合は、ポインターを使用する必要があります 。 (ポインターを使用しないと、オブジェクトのスライシングという恐ろしい問題が発生します。すべてのオブジェクトは静かに表示されます。基本クラス型に変換されます。これはコンパイラによって診断されず、ほぼ間違いなくあなたが望むものではありません。)
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
など、スマートポインターの使用を絶対に検討する必要があります。
はい、確かです。
// 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
を使用する必要があります。
ポインタのベクトル用にvector<c*>
を作成しました。次に、new
を使用してcオブジェクトにメモリを割り当て、それらをベクトルにプッシュします。また、delete
する必要があることを忘れないでください。vector.clear()はcオブジェクトに割り当てられたメモリを解放しません。ここにcをポインターのベクトルとして保存する必要があります。そうしないと、仮想関数の呼び出しが機能しません。
ブーストポインタコンテナライブラリをお試しください。次のように、ポインターの通常のベクターに比べていくつかの利点があります。
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