web-dev-qa-db-ja.com

オブジェクトを参照するSTLコンテナー

STLコンテナーがオブジェクトをコピーすることを知っています。だから私が持っていると言う

list<SampleClass> l;

私がするたびに

SampleClass t(...);
l.Push_back(t);

tのコピーが作成されます。 SampleClassが大きい場合は、非常にコストがかかります。

しかし、lを参照のコンテナとして宣言すると、

list<SampleClass&> l;

私がする時

l.Push_back(t);

オブジェクトのコピーを避けますか?

28
Vendetta

悲しいことに、それはコンパイルされません(少なくともstlportでは)。ただし、コンテナへのオブジェクトへのポインタを格納するという代替手段は、完全に正常にコンパイルされます。

これにより、コードの周りに余分な構文ノイズが残ります。それらをコンテナーに挿入するには、新しいものを用意する必要があります。

std::list<class_type*> l;
l.Push_back(new class_type);

ただし、オブジェクトはコピーされなくなりますが、リストが破棄されたときに自動的にクリーンアップされません。スマートポインターはこれを解決しますが、構文ノイズがさらに増えます。また、std :: auto_ptrはコピーできないため、標準のコンテナーに配置することはできないため、やや重いブーストのいとこ、共有ポインターを使用する必要があります。

std::list<boost::shared_ptr<class_type> > l;
l.Push_back(boost::shared_ptr<class_type>(new class_type));

共有ポイントは、いくつかの余分なオーバーヘッドが発生しますが、それは最小限です。

20
Dave Branton

何をしているのかわかっている場合は、std::reference_wrapperを使用して参照のベクトルを作成できます。

#include <functional>
#include <vector>

int main()
{
  std::vector<std::reference_wrapper<int>> iv;

  int a = 12;
  iv.Push_back(a);  // or std::ref(a)

  // now iv = { 12 };

  a = 13;

  // now iv = { 13 };
}

もちろん、参照されている変数の参照を保持したまま、参照されている変数のいずれかがスコープ外になると、これらのいずれかがクラッシュします。

31
Kerrek SB

標準ライブラリコンテナでは、そのタイプをコピー可能にする必要があります。参照はそうではないので、そもそもコンテナに格納することはできません。オブジェクトの存続期間に注意している限り、ポインタを格納できます。 Boostには、それを支援するためのポインターコンテナーがいくつかあります。そうでなければ、スマートポインターがあります。ただし、auto_ptrnotコピー可能(標準ではこの目的で定義されているため)なので、shared_ptrおよびunique_ptrが最善策です。どちらもC++ 11の標準であり、前者はC++ 03のboostを通じてサポートされます。

4

ポインタのコンテナが必要です:

list<SampleClass*> l;
1
Mikhail

スマートポインターを取得したので、それを使用してメモリ管理を行い、生のポインターを取得してSTLコンテナーで使用できます。このようにして、所有権をコンテナーから除外します。

ここで私は木のunique_ptrを持っていますが、生のポインタを格納するためにSTLスタックを使用しました

void TreeTraversal(unique_ptr<BinaryTreeNode>& root) {
    stack<BinaryTreeNode *> _stack;

    BinaryTreeNode *p = root.get();
    _stack.Push(p);

    while(!_stack.empty()) {
        p = _stack.top();
        _stack.pop();
        ...
        _stack.Push(p->left);
        _stack.Push(p->right);
    }
}

int main() {
    unique_ptr<BinaryTreeNode> root = unique_ptr<BinaryTreeNode>(new BinaryTreeNode(...));
    TreeTraversal(root);
}
0
saha