関数set::insert
は要素またはそのコピーへのポインタを保存しますか?つまり、次のコードを実行できますか、それともポインタが削除されていないことを確認する必要がありますか?
int *a;
*a=new int(1);
set<int> _set;
_set.insert (*a);
delete a;
*a=new int(2);
_set.insert (*a);
delete a;
で例を示しましたint
が、実際のプログラムでは、作成したクラスを使用しています。
すべての STL コンテナーは、挿入されたデータのコピーを格納します。3 番目の段落のセクション「説明」を参照してください。コンテナ (およびコンテナのモデル)std::set
は、その要素を所有しています。詳細については、次の脚注 [1] を参照してください。特に、ここの「タイプ要件」セクションの下std::set
を見てください。は割り当て可能である必要があります。Key
それとは別に、これを簡単にテストできます:
struct tester {
tester(int value) : value(value) { }
tester(const tester& t) : value(t.value) {
std::cout << "Copy construction!" << std::endl;
}
int value;
};
// In order to use tester with a set:
bool operator < (const tester& t, const tester& t2) {
return t.value < t2.value;
}
int main() {
tester t(2);
std::vector<tester> v;
v.push_back(t);
std::set<tester> s;
s.insert(t);
}
あなたはいつも見るでしょうCopy construction!
。
オブジェクトへの参照のようなものを本当に保存したい場合は、これらのオブジェクトへのポインターを保存できます。
tester* t = new tester(10);
{
std::set<tester*> s;
s.insert(t);
// do something awesome with s
} // here s goes out of scope just as well the contained objects
// i.e. the *pointers* to tester objects. The referenced objects
// still exist and thus we must delete them at the end of the day:
delete t;
ただし、この場合、オブジェクトを正しく削除するように注意する必要があり、これが非常に難しい場合があります。たとえば、例外は実行のパスを劇的に変更する可能性があり、正しい場所に到達することはありませんdelete
。
または、次のようなスマート ポインターを使用できますboost::shared_ptr
。
{
std::set< boost::shared_ptr<tester> > s;
s.insert(boost::shared_ptr<tester>(new tester(20)));
// do something awesome with your set
} // here s goes out of scope and destructs all its contents,
// i.e. the smart_ptr<tester> objects. But this doesn't mean
// the referenced objects will be deleted.
これで、スマート ポインターが面倒を見て、適切なタイミングで参照オブジェクトを削除します。挿入されたスマート ポインターの 1 つをコピーして別の場所に転送した場合、一般的に参照されるオブジェクトは、このオブジェクトを参照する最後のスマート ポインターが範囲外になるまで削除されません。
ところで、標準コンテナの要素として s を使用しないでください。std::auto_ptr
それらの奇妙なコピー セマンティクスは、コンテナーがデータを格納および管理する方法、および標準アルゴリズムがそれらを操作する方法と互換性がありません。この不安定な問題に関して、StackOverflow には多くの質問があると思います。
std::set
挿入した要素をコピーします。
ポインターをセットに保存しています。
ポインターが指すオブジェクトはコピーされません。
したがって、削除を呼び出した後、セット内のポインターは無効になります。
注: おそらく整数だけを保存したいでしょう。
int a(1);
set<int> s;
s.insert(a); // pushes 1 into the set
s.insert(2); // pushes 2 into the set.
その他の注意事項:
std::auto_ptr<int> a(new int(1));
set<int*> s;
s.insert(a.release());
// Note. Set now holds a RAW pointer that you should delete before the set goes away.
// Or convert into a boost::ptr_set<int> so it takes ownership of the pointer.
int *a;
*a=new int(1);
a
ガベージであるaddress に格納されている値を使用しようとしているため、このコードは間違っています。
また、 C++0x で右辺値参照を取得する insert() および push_back() でセマンティクスを使用しない限り、すべての stl コンテナーcopy
要素。move