Вопрос

I am returning multimap iterator from called function.

code:

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;  

And calling function:

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

Here Why I could not print content of rec directly? In called function std::cout<<it->second<<":"<<it->first<<std::endl; prints correct value!

Entire code:

#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;

}
Это было полезно?

Решение

You cannot return iterator to local object, it becomes invalid when you return from function and local object multimap dst is destroyed. You need another design, maybe create object on the free store (return sharedpointer?) or make it static, or pass by reference like this:

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();  
    } 

usage:

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;
}

Note: also return dst.begin() not it, because otherwise you might face undefined behavior: it might point out of range because it was incremented before return in client().

Другие советы

The lifetime of the object dst ends when you return from the function client. At that point, iterators obtained from the map become invalid, and it is undefined behaviour to dereference them.

An iterator is essentially a pointer, and you're returning an iterator to a local variable that will expire at the end of the client call. That's why you're getting garbage values.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top