4
#include <unordered_map>
#include <string>
#include <iostream>
#include <algorithm>
#include <utility>

int main() 
{
  std::unordered_map<string, int> hash {{"a", 1}, {"b", 2}, {"c", 3}};

  // CaseA(NO-ERROR)
  std::for_each(hash.begin(), hash.end(),
    [](const std::pair<string, int>& p) {
      std::cout << p.first << " => " << p.second << endl;
    }
  );

  // CaseB(NO-ERROR)
  std::for_each(hash.begin(), hash.end(),
    [](const std::pair<string, int> p) {
      std::cout << p.first << " => " << p.second << endl;
    }
  );

  // CaseC(NO-ERROR)
  std::for_each(hash.begin(), hash.end(),
    [](std::pair<string, int> p) {
      std::cout << p.first << " => " << p.second << endl;
    }
  );

  // CaseD(ERROR)
  std::for_each(hash.begin(), hash.end(),
    [](std::pair<string, int>& p) {
      std::cout << p.first << " => " << p.second << endl;
    }
  );

}

Q1> CaseD が間違っているのはなぜですか?

Q2> CaseAが推奨されるというのは本当ですか?

ありがとうございました

4

2 に答える 2

14

value_typeは( に注意してくださいstd::unordered_map<K,V>)です。type の参照を typeのオブジェクトにバインドすることはできません。タイプの名前を直接綴ろうとする代わりに、を使用する必要があります。これにより、間違いを防ぐことができます。std::pair<const K,V>conststd::pair<K,V>std::pair<const K,V>std::unordered_map<K,V>::value_type

ご参考までに、ケース C は、型の変換を可能にするコンストラクターがあるため動作するためpstd::unordered_map.

コンテナ内の要素を変更することを意図していないラムダの推奨される方法は次のとおりです。

[](const std::unordered_map<std::string,int>::value_type& p)

質問の最初の 3 つのケースでは、要素のコピーが行われます (パフォーマンス ヒット)。呼び出し元の観点からは、ケース B と C は同じです (関数では、最上位の修飾子が削除されます) が、ラムダ ケース B の定義の観点からは、そうしないことが保証されます。引数の変更を試みます (それ自体がソースのコピーです)

于 2013-06-25T20:22:27.067 に答える
5

あなたの問題は、コンテナがいっぱいになっていることですstd::pair<const string, int>。ケース 1 から 3 の場合、コンテナ内の を暗黙的にstd::pair<const string, int>に変換し、その一時をラムダに渡すことができます。std::pair<string, int>

C++11 でコンテナーの各要素に対して非変更を行うための推奨される方法は次のとおりです。

for( auto const& p: hash ) {
  std::cout << p.first << " => " << p.second << endl;
}

これは冗長性が低く、DRY に違反していません。理にかなっている場合は、反復子ベースの反復ではなく、コンテナー ベースの反復を優先します。

コンテナー ベースのstd::アルゴリズムとauto型付きラムダの間std::で、C++ の 1 つまたは 2 つのバージョンでアルゴリズムを使用することが再び魅力的になります。それでも、ラムダを使用している種類のアルゴリズムを抽象化している場合を除き、for_each今では非常に疑わしいものfor_eachです。

于 2013-06-25T21:37:16.943 に答える