【问题标题】:How to return the content of std::pair?如何返回 std::pair 的内容?
【发布时间】:2013-09-04 18:00:13
【问题描述】:

我正在尝试返回具有 intstring 值的 std::pair 的内容。 我应该保留什么函数的返回类型?

我尝试使用 intchar 返回类型,但两者都出现错误。我在下面给出了错误:

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

    std::pair<int,std::string>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();  // Error  no match for ‘operator=’ in ‘rec = client()()’
std::multimap<int,std::string>::iterator it = rec.begin();  //error: ‘std::multimap<int, std::basic_string<char> >::const_iterator’ has no member named ‘begin’

 for(int count = 0;count<3 && rec !=it.end();++it,++count) // error: has no member named 'end' 
   std::cout<<rec->second<<":"<<rec->first<<std::endl;

}

【问题讨论】:

  • 呃,返回这对本身?
  • std::pair&lt;int, std::string&gt; client() ?
  • 如果你有 C++11,使用 auto 关键字。
  • @Karimkhan 增加与字符串 x 关联的 int。它从 0 开始。
  • 你应该使用 const auto& 来避免复制字符串。

标签: c++ return return-value


【解决方案1】:

只需返回 intstd::string 对本身 因为multimap 包含它作为它的元素

std::pair<int,std::string> client(){
//...  
}

【讨论】:

  • 直到它给出很长的错误信息,我不知道错误在哪里!
  • @Karimkhan,您必须插入元素,而不是分配它。
  • @Karimkhan 我认为您从here 获取了我的代码因此,如果您想将迭代器返回到第一个元素,您需要使用std::multimap&lt;int,std::string&gt;::iterator client() {...return it;} 在有问题的标题中也没有询问:P跨度>
  • @chris 我认为 OP 需要前三个元素,昨天提出了类似的问题
  • @Karimkhan 如果您继续更改代码,答案将毫无意义。告诉使用你到底想要什么?你不能像那样使用迭代器。我假设您想要 dst 地图内容,为什么不简单地返回 multimap ?您可能希望以明确的问题和错误开始一个新线程
【解决方案2】:

如果您想返回映射条目(即键和值),则只需使用 std::pair&lt;int, std::string&gt; 作为返回类型,正如其他答案所述。

如果您只想返回密钥,请返回 it-&gt;first(并使用 int 作为返回类型)。如果您只想返回值,请返回 it-&gt;second(并使用 std::string 作为返回类型)。

【讨论】:

  • 直到它给出很长的错误信息,我不知道错误在哪里!
【解决方案3】:

如果您想从 std::map 返回 a 值,我不会明确使用 std::pair(尽管这样做非常好)。我个人会使用 std::map::value_type 表示存储在映射中的值的类型(注意:所有容器都有一个名为 value_type 的类型成员,表示正在存储的类型)。

std::multimap<int,std::string>::value_type client()
{
     // STUFF
     std::multimap<int,std::string>::iterator it = dst.begin();

     // STUFF;
     return *it;   // Note: this is UB if it == dst.end()
}

我使用value_type 而不是std::pair 的原因通常是我不会使用显式类型,但会创建typedef(所以看起来像这样)。

typedef std::multimap<int,std::string>  MapForX; // Modification to map here
                                                 // Will automatically roll threw all
                                                 // the following code as everything
                                                 // is defined in terms of `MapForX`

MapForX::value_type client()
{
     // STUFF
     MapForX::iterator it = dst.begin();

     // STUFF;
     return *it;   // Note: this is UB if it == dst.end()
}

现在,如果我更改 MapForX 的类型。然后我只需要更改一件事(单个 typedef)。如果您返回std::pair&lt;int,std::string&gt;,那么您必须在两个地方进行更改(typedef 和返回值)。对我来说,这是可能导致问题的多余更改。

作为演示:如果您返回 std::pair&lt;int, std::string&gt;,您的代码如下所示:

typedef std::multimap<int,std::string>  MapForX; // Modification to map here
                                                 // Will automatically roll threw MOST
                                                 // the following code.

// But notice this return type is not defined in terms of MapForX
// Thus if you change MapForX you will also need to change the return type.
// to match the correct type.
std::pair<int, std::string> client()
{
     // STUFF
     MapForX::iterator it = dst.begin();

     // STUFF;
     return *it;   // Note: this is UB if it == dst.end()
}

效果很好。但在未来,你必须做出一些改变。你也改变了地图的类型int =&gt; MySpecialType。现在在我的第二个示例(使用 typedef)中,您只需要进行一项更改(在 MapForX 中)。在上面的示例中,您需要进行两项更改(一项针对 MapForX,一项针对返回类型的 std::pair)。

【讨论】:

  • 谢谢,很好的解释。但我不明白为什么需要第二个代码?
  • @Karimkhan:它不是“需要的”。但是为了使代码更易于阅读和更新,有时 typedef 类型更容易。问题是你认为它是否更容易阅读。如果你这样做,那么使用 typedef。如果你不使用完整的类型名。这是个人对可读性的偏好。但是随着您的类型变得越来越复杂,这种技术会派上用场。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-08
  • 2020-04-22
  • 1970-01-01
  • 2012-12-12
  • 1970-01-01
  • 1970-01-01
  • 2012-09-19
相关资源
最近更新 更多