【问题标题】:Why can't I do std::map.begin() + 1?为什么我不能做 std::map.begin() + 1?
【发布时间】:2013-07-03 06:56:53
【问题描述】:

我有一个 std::map,我想从第二个条目开始对其进行迭代。

我可以很好地解决这个问题,但我对为什么“显而易见”的语法无法编译感到困惑。错误消息没有帮助,因为它引用了std::string,我在这里没有使用。

这里有一些代码

// Suppose I have some map ...
std::map<int, int> pSomeMap;

// This is fine ...
std::map<int, int>::const_iterator pIterOne = pSomeMap.begin();
++pIterOne;

// This doesn't compile ...
std::map<int, int>::const_iterator pIterTwo = pSomeMap.begin() + 1;

Visual Studio 2012 在上述行出现以下错误:

error C2784: 'std::_String_iterator<_Mystr> std::operator +
(_String_iterator<_Mystr>::difference_type,std::_String_iterator<_Mystr>)' :
could not deduce template argument for 'std::_String_iterator<_Mystr>' from 'int'

这里发生了什么?

【问题讨论】:

  • 有史以来最奇怪的错误信息?
  • @NathanOliver:如果您正在编辑帖子以将错误消息从引号移动到代码块,我可以建议添加 &lt;!-- language: lang-none --&gt; 以禁用语法突出显示吗?

标签: c++ visual-c++ visual-studio-2012 stl


【解决方案1】:

std::map 迭代器是双向的,因此它们只提供 ++ 和 -- 运算符,但不提供 operator+,即使它是 +1。
如果确实需要模拟 operator+,可以使用std::advance,但这会导致迭代器调用递增序列。

【讨论】:

  • 它为什么选择抱怨字符串?
  • 这很有帮助,谢谢,虽然像@doctorlove 一样,我仍然不明白编译器错误。我想知道其他编译器报告了什么。
  • @doctorlove 最好问问 msvc 编译器开发人员。 gcc 给出了所有可能的扣除。 ideone.com/UUz5Xr
【解决方案2】:

std::map&lt;T&gt;::iterator 属于迭代器类双向迭代器。那些只有++-- 运算符。 +N[] 仅可用于随机访问迭代器(可以在例如 std::vector&lt;T&gt; 中找到)。

这背后的原因是,将N 添加到随机访问迭代器 是恒定时间(例如,将N*sizeof(T) 添加到T*),而对双向迭代器需要应用++N次。

你可以做的(如果你有 C++11)是:

std::map<int, int>::const_iterator pIterTwo = std::next(pSomeMap.begin(),1);

这对所有迭代器类型都是正确的。

【讨论】:

  • 太棒了 - std::next 对我来说也更干净。谢谢+1。
  • @RogerRowland 请注意,std::next 是 C++11 添加的。但是如果你没有 C++11,使用std::advance 实现你自己的next 是很容易的。或使用boost::next
  • @juanchopanza 谢谢,我有 VS2012,这可能是 MS 最接近 C++11 的版本!它编译并运行良好。
猜你喜欢
  • 2019-06-01
  • 2018-10-24
  • 2020-08-05
  • 1970-01-01
  • 2015-04-30
  • 2012-01-17
  • 2011-01-22
相关资源
最近更新 更多