62

を使用して定義された文字列の連想配列の反復に関連する次の問題がありますstd::map

-- snip --
class something 
{
//...
   private:
      std::map<std::string, std::string> table;
//...
}

コンストラクターでは、文字列データに関連付けられた文字列キーのペアをテーブルに入力します。他の場所にtoString、テーブルオブジェクトに含まれるすべてのキーと関連データを含む文字列オブジェクトを返すメソッドがあります(key = data形式として)。

std::string something::toString() 
{
        std::map<std::string, std::string>::iterator iter;
        std::string* strToReturn = new std::string("");

        for (iter = table.begin(); iter != table.end(); iter++) {
           strToReturn->append(iter->first());
           strToReturn->append('=');
           strToRetunr->append(iter->second());
           //....
        }
       //...
}

コンパイルしようとすると、次のエラーが発生します。

error: "error: no match for call to ‘(std::basic_string<char,
    std::char_traits<char>, std::allocator<char> >) ()’".

誰かが私に何が欠けているのか、私が間違っているのかを説明してもらえますか?ユーザーがオブジェクトhash_mapで使用できるようにハッシュ関数を定義する必要がある場合に、同様の問題についての議論をいくつか見つけました。私の場合も似たようなものでしょうか?hash_mapstd::string

4

8 に答える 8

74

主な問題はfirst()、イテレータで呼び出されたメソッドを呼び出していることです。あなたがすることを意図しているのは、first:と呼ばれるプロパティを使用することです。

...append(iter->first) rather than ...append(iter->first())

newスタイルの問題として、その文字列を作成するために使用するべきではありません。

std::string something::toString() 
{
        std::map<std::string, std::string>::iterator iter;
        std::string strToReturn; //This is no longer on the heap

        for (iter = table.begin(); iter != table.end(); ++iter) {
           strToReturn.append(iter->first); //Not a method call
           strToReturn.append("=");
           strToReturn.append(iter->second);
           //....
           // Make sure you don't modify table here or the iterators will not work as you expect
        }
        //...
        return strToReturn;
}

編集: facildelembrarは(コメントで)最新のC++ではループを書き直すことができると指摘しました

for (auto& item: table) {
    ...
}
于 2009-07-01T00:00:40.657 に答える
19
  1. toString()メソッドを書かないでください。これはJavaではありません。クラスのストリーム演算子を実装します。

  2. 独自のループを作成するよりも、標準のアルゴリズムを使用することをお勧めします。この状況でstd::for_each()は、あなたがやりたいことへの素晴らしいインターフェースを提供します。

  3. ループを使用する必要があるが、データを変更するつもりがない場合は、よりも優先const_iteratorしてiteratorください。そうすれば、誤って値を変更しようとした場合、コンパイラは警告を発します。

それで:

std::ostream& operator<<(std::ostream& str,something const& data)
{
    data.print(str)
    return str;
}

void something::print(std::ostream& str) const
{
    std::for_each(table.begin(),table.end(),PrintData(str));
}

次に、それを印刷する場合は、オブジェクトをストリーミングするだけです。

int main()
{
    something    bob;
    std::cout << bob;
}

オブジェクトの文字列表現が実際に必要な場合は、を使用できますlexical_cast

int main()
{
    something    bob;

    std::string  rope = boost::lexical_cast<std::string>(bob);
}

記入する必要のある詳細。

class somthing
{
    typedef std::map<std::string,std::string>    DataMap;
    struct PrintData
    {
         PrintData(std::ostream& str): m_str(str) {}
         void operator()(DataMap::value_type const& data) const
         {
             m_str << data.first << "=" << data.second << "\n";
         }
         private:  std::ostream& m_str;
    };
    DataMap    table;
    public:
        void something::print(std::ostream& str);
};
于 2009-07-01T00:15:47.600 に答える
4

追加呼び出しを次のように変更します

...append(iter->first)

... append(iter->second)

さらに、ライン

std::string* strToReturn = new std::string("");

ヒープに文字列を割り当てます。この動的に割り当てられた文字列へのポインタを実際に返す場合は、戻り値をstd ::string*に変更する必要があります。

または、ヒープ上でそのオブジェクトを管理することを心配したくない場合は、ローカル宣言を次のように変更します。

std::string strToReturn("");

'append'呼び出しを変更して、参照構文を使用します。

strToReturn.append(...)

それ以外の

strToReturn->append(...)

これにより、スタック上に文字列が作成され、それが戻り変数にコピーされることに注意してください。これはパフォーマンスに影響します。

于 2009-07-01T00:01:45.820 に答える
2

iter->firstiter->secondは変数であり、メソッドとして呼び出そうとしています。

于 2009-06-30T23:59:46.917 に答える
2

std :: map::iteratorの間接参照の結果はstd::pairであることに注意してください。との値は関数firstsecondはなく、変数です。

変化する:

iter->first()

iter->first

同上iter->second

于 2009-07-01T00:02:48.953 に答える
1

使用する:

std::map<std::string, std::string>::const_iterator

代わりは:

std::map<std::string, std::string>::iterator
于 2013-04-26T08:51:24.627 に答える
0

c ++ 11では、次を使用できます。

for ( auto iter : table ) {
     key=iter->first;
     value=iter->second;
}
于 2014-01-19T00:52:31.843 に答える
0

もう1つの価値のある最適化は、STL文字列クラスのc_str()メンバーです。これは、 LPCTSTRとして、たとえばLPCTSTRを期待するカスタム関数に渡すことができる不変のnullで終了する文字列を返します。デストラクタをトレースして確認していませんが、文字列クラスがコピーを作成するメモリを管理しているのではないかと思います。

于 2014-09-07T00:37:43.193 に答える