std::pair<const T, const U>
C++ では、との動作の違いは何const std::pair<T, U>
ですか?
2 に答える
主な違いは、それらが異なる無関係な型であることです (それらの間にいくつかの暗黙的な変換があります)。
void f(std::pair<std::string,std::string> const &);
std::string longstring();
int main() {
std::pair<const std::string,const std::string> pc
= std::make_pair(longstring(),longstring());
f(pc);
const std::pair<std::string,std::string> cp
= std::make_pair(longstring(),longstring());
f(cp);
}
f(pc)
コンパイルを許可する暗黙の変換がありますが、その行には変換が含まれ、変換にはs のコピーの作成が含まれlongstring()
ます。一方、呼び出しf(cp)
は、型が一致する既存のペアへの定数参照のみをバインドし、コピーは必要ありません。
コンパイラが似たようなコードを書けるという事実は、そのコードが同じことをするようにコンパイルされているという意味ではありません。これは、暗黙的な変換を伴う型に特に当てはまります。std::pair
これは、マップに格納された要素を操作するファンクターを作成するときによくある落とし穴です。ファンクターの引数の不一致により、オブジェクト データの不要なコピーが発生します。
std::map<int,std::string> m = create_map();
std::for_each(m.begin(),m.end(),
[](std::pair<int,std::string> const &r) {
std::cout << r.second << " ";
});
上記のラムダには正しい型の引数 ( std::pair<int,std::string
vs. std::pair<const int,std::string>
) がなく、呼び出しごとにインデックスと値の両方がコピーされます (つまり、すべての文字列が にコピーされ、std::pair<int,std::string>
次に引数のバインドされた参照がラムダにコピーされます)。 . この場合の簡単な推奨事項はstd::map<int,std::string>::value_type const &
、引数の型に使用することです。
私が行ったテストから、動作は同じです。
#include <utility>
int main() {
std::pair<const int, const int> p = std::make_pair(2,3);
p = std::make_pair(3, 4); // error
p.first = 5; // also error
const std::pair<int, int> p2 = std::make_pair(4,5);
p2 = std::make_pair(4, 5); // error
p2.first = 0; // error
return 0;
}