web-dev-qa-db-ja.com

std :: map :: iteratorは値のコピーまたは値自体を返しますか?

マップ内にマップを作成しようとしています:

typedef map<float,mytype> inner_map;
typedef map<float,inner_map> outer_map;

内部マップ内に何かを入れることはできますか、それともiterator :: secondはコピーを返しますか?

stl_pair.hは後者を示唆しています:

74: _T2 second;          ///< @c second is a copy of the second object

しかし、私のテストプログラムは、次のようなコードで正常に実行されます。

it = my_map.lower_bound(3.1415);
(*it).second.insert(inner_map::value_type(2.71828,"Hello world!");

では、真実はどこにあるのでしょうか。これはコピーですか?

25
Morse

stl_pair.hのコメントは、この特定のケースでは誤解を招く可能性があります。

map::iteratorは実際にはマップ内の元のデータを参照しているため、noコピーがあります(value_type、それ自体はpair)、それはコピーではありません。したがって、iterator::secondは元のデータも参照します。

25
Konrad Rudolph

C++ 11イテレータを使用している人のために、この質問に対するフォローアップの回答を追加したいと思います...

次のコード:

std::map<std::string, std::string> m({{"a","b"},{"c","d"}});
for (auto i : m)
{
    std::cout << i.first << ": " << i.second << std::endl;
}

does "auto"はデフォルトで値であり、const参照ではないため、キーと値をコピーします(少なくとも、clang 3.1の動作はこのようになります)。

さらに、コード:

std::map<std::string, std::string> m({{"a","b"},{"c","d"}});
for (const std::pair<std::string,std:string>& i : m)
{
    std::cout << i.first << ": " << i.second << std::endl;
}

また正しいコードは次のようになるため、キーと値をコピーします。

std::map<std::string, std::string> m({{"a","b"},{"c","d"}});
for (const auto& i : m)
{
    std::cout << i.first << ": " << i.second << std::endl;
}

または

std::map<std::string, std::string> m({{"a","b"},{"c","d"}});
for (const std::pair<const std::string,std:string>& i : m)
{
    std::cout << i.first << ": " << i.second << std::endl;
}
27
Matt Gallagher

value_typeマップはペアであるため、最初と2番目のメンバーがあります。すべてのイテレータと同様に、マップイテレータは疑似ポインタです。つまり、コレクション内のデータを指し、そのデータのコピーを指しません。

イテレータは再割り当て可能であり(つまり、イテレータを使用するため)、他のオブジェクトを参照するために参照を再割り当てできないため、内部的には参照ではなくポインタが含まれることはほぼ確実です。

Const_iteratorがあり、その下の型がPODである場合でも、誰かがこれを行う場合に備えて、それへのポインターが必要です。

map< int, int > m;
m.insert( make_pair( 1, 2 );
map<int,int>::const_iterator citer = m.begin();
map<int,int>::iterator iter = m.begin();
iter->second = 3;
std::cout << citer->second << '\n'; // should always print 3

動作を定義し、3を出力する必要があります。これは、const_iteratorがconstであり、intのみである後に「最適化」することを決定した場合には発生しません。

4
CashCow

イテレータは、参照が解除されると、 参照を提供します