2

呼び出された関数からマルチマップ イテレータを返しています。

コード:

std::multimap<int,std::string>::iterator it = dst.begin();

     for(int count = 0;count<3 && it !=dst.end();++it,++count)
       std::cout<<it->second<<":"<<it->first<<std::endl;

     return it;  

そして呼び出し関数:

std::multimap<int,std::string>::const_iterator rec;
    rec= client(); 

    for(int count = 0;count<3 ;++count)
       std::cout<<rec->second<<":"<<rec->first<<std::endl; // Prints garbage values

recここ のコンテンツを直接印刷できないのはなぜですか? 呼び出された関数でstd::cout<<it->second<<":"<<it->first<<std::endl;は、正しい値が出力されます!

コード全体:

#include<iostream>
#include<algorithm>
#include<map>
#include<vector>

std::multimap<int,std::string>::iterator client()  
{

    std::vector<std::string> most { "lion","tiger","kangaroo",
                                     "donkey","lion","tiger",
                                     "lion","donkey","tiger"
                                     };
    std::map<std::string, int> src;
    for(auto x:most)
        ++src[x];

    std::multimap<int,std::string,std::greater<int> > dst;

    std::transform(src.begin(), src.end(), std::inserter(dst, dst.begin()), 
                       [] (const std::pair<std::string,int> &p) {
                       return std::pair<int,std::string>(p.second, p.first);
                       }
                     );

    std::multimap<int,std::string>::iterator it = dst.begin();

    for(int count = 0;count<3 && it !=dst.end();++it,++count)
        std::cout<<it->second<<":"<<it->first<<std::endl;

    return it;  
}

int main()
{

    std::multimap<int,std::string>::const_iterator rec;
    rec= client(); 

    for(int count = 0;count<3 ;++count,++rec)
    std::cout<<rec->second<<":"<<rec->first<<std::endl;

}
4

3 に答える 3

2

ローカル オブジェクトにイテレータを返すことはできません。関数から戻ると無効になり、ローカル オブジェクトmultimap dstが破棄されます。別の設計が必要です。おそらく、フリー ストアにオブジェクトを作成するか (sharedpointer を返しますか?)、静的にするか、次のように参照渡しします。

std::multimap<int,std::string>::iterator 
          client(std::multimap<int,std::string,std::greater<int> >& dst) {

    std::vector<std::string> most { "lion","tiger","kangaroo",
                                     "donkey","lion","tiger",
                                     "lion","donkey","tiger"
                                     };
    std::map<std::string, int> src;
    for(auto x:most)
        ++src[x];

    std::transform(src.begin(), src.end(), std::inserter(dst, dst.begin()), 
                       [] (const std::pair<std::string,int> &p) {
                       return std::pair<int,std::string>(p.second, p.first);
                       }
                     );

    std::multimap<int,std::string>::iterator it = dst.begin();

     for(int count = 0;count<3 && it !=dst.end();++it,++count)
       std::cout<<it->second<<":"<<it->first<<std::endl;

     return dst.begin();  
    } 

利用方法:

int main(){
    std::multimap<int,std::string,std::greater<int> > dst;
    std::multimap<int,std::string>::const_iterator rec;
    rec = client(dst);

    for(int count = 0;count<3 ;++count,++rec)
       std::cout<<rec->second<<":"<<rec->first<<std::endl;

return 0;
}

注: また、 dst.begin()notitを返します。そうしないと、未定義の動作に直面する可能性があるためclient()です。

于 2013-09-01T17:02:50.763 に答える
1

dst関数から戻ると、オブジェクトの存続期間は終了しますclient。その時点で、マップから取得したイテレータは無効になり、それらを逆参照するのは未定義の動作です。

于 2013-09-01T16:47:58.477 に答える
1

clientイテレータは基本的にポインタであり、呼び出しの最後に有効期限が切れるローカル変数にイテレータを返します。そのため、ガベージ値を取得しています。

于 2013-09-01T16:49:29.160 に答える