【问题标题】:what does the error mean when I am compiling c++ with g++ compiler?当我使用 g++ 编译器编译 c++ 时,错误是什么意思?
【发布时间】:2012-03-29 21:28:56
【问题描述】:

使用以下代码:

#include<iostream>
#include<vector>

using namespace std;

int main()
{
    vector<int> ivec;
    for(vector<int>::size_type ix = 0; ix != 10; ix++)
    {
        ivec.push_back(ix);
    }
    vector<int>::iterator mid = (ivec.begin() + ivec.end()) / 2;
    cout << *mid << endl;
    return 0;
}

使用 g++ 编译时出错:

iterator_io.cpp: In function `int main()':
iterator_io.cpp:13: error: no match for 'operator+' in '(&ivec)->std::vector<_Tp,               _Alloc>::begin [with _Tp = int, _Alloc = std::allocator<int>]() + (&ivec)->std::vector<_Tp, _Alloc>::end [with _Tp = int, _Alloc = std::allocator<int>]()'
/usr/lib/gcc/x86_64-redhat-linux/3.4.5/../../../../include/c++/3.4.5/bits/stl_iterator.h:654: note: candidates are: __gnu_cxx::__normal_iterator<_Iterator, _Container> __gnu_cxx::__normal_iterator<_Iterator, _Container>::operator+(const typename std::iterator_traits<_Iterator>::difference_type&) const [with _Iterator = int*, _Container = std::vector<int, std::allocator<int> >]
/usr/lib/gcc/x86_64-redhat-linux/3.4.5/../../../../include/c++/3.4.5/bits/stl_bvector.h:261: note:                 std::_Bit_iterator std::operator+(ptrdiff_t, const std::_Bit_iterator&)
/usr/lib/gcc/x86_64-redhat-linux/3.4.5/../../../../include/c++/3.4.5/bits/stl_bvector.h:345: note:                 std::_Bit_const_iterator std::operator+(ptrdiff_t, const std::_Bit_const_iterator&)
/usr/lib/gcc/x86_64-redhat-linux/3.4.5/../../../../include/c++/3.4.5/bits/stl_iterator.h:765: note:                 __gnu_cxx::__normal_iterator<_Iterator, _Container> __gnu_cxx::operator+(typename __gnu_cxx::__normal_iterator<_Iterator, _Container>::difference_type, const __gnu_cxx::__normal_iterator<_Iterator, _Container>&) [with _Iterator = int*, _Container = std::vector<int, std::allocator<int> >]

我知道 ivec.end() 不能用作法线向量元素。但是我不明白错误信息是什么意思......关于operator+的东西?

【问题讨论】:

  • +1 表示第一个问题问得好、格式好、标签正确。
  • +1 包含一个简短而完整的示例程序。 sscce.org

标签: c++ vector iterator compiler-errors


【解决方案1】:

不能将两个迭代器加在一起。

operator+ 没有为两个迭代器定义,因为该操作没有意义。迭代器是对指针的一种概括——它们指向存储在容器中的特定元素。迭代器的总和指向哪个元素?

但是,当您使用向量时,您可以将整数添加到迭代器,如下所示:

vec.begin() + vec.size() / 2

这就是为什么您的错误消息中有candidates are: (...),后跟operator+ 的一些定义。

在您的情况下,最好、最干净的方法不是使用迭代器,而是简单的从指定位置获取值

int mid = vec[vec.size() / 2];

【讨论】:

  • 在这里使用at 是非正统的,至少可以这么说。在目前的情况下,不可能永远出现访问错误,那么为什么要提防它呢?
  • 我同意,at() 改为 []
【解决方案2】:

您不能添加迭代器。你可以做什么:

vector<int>::iterator mid = ivec.begin() + distance(ivec.begin(), ivec.end()) / 2;

【讨论】:

  • distance(vector::begin, vector::end) 不会和vector::size 一样吗?
  • @PeterWood - 在这种情况下,是的。但距离也适用于其他容器,而不仅仅是矢量。
  • @PeterWood:我认为这个想法是,你可以使用任意两个迭代器,beb+distance(b,e)/2 会给你在b 和中间的位置e。所以,它更笼统一些。
  • @bitmask:嗯,假设你有operator+(Iter, offset_t)(即随机迭代器),而对于那些你可以使用operator-(Iter, Iter)。因此,完全便携且高效的替代方案是ivec.begin + (ivec.end()-ivec.begin())/2;。即使容器是空的,这也是有效的。
  • @JonPurdy:没错,std::advance 也是如此(专门用于使用operator+)。也许我应该更明确一点:为了保持一致,将std::advancestd::distance 结合使用,将operator+operator- 结合使用。
【解决方案3】:

这只是意味着vector 迭代器没有加法运算符(+)。不能添加ivec.begin()ivec.end()

要获取中间元素,你可以简单地使用下标运算符:

cout << ivec[ivec.size()/2] << endl;

如果你坚持使用迭代器,你可以通过这种方式得到一个指向中间的迭代器:

vector<int>::iterator mid = ivec.begin();
mid += ivec.size()/2;
cout << *mid << endl;

您可以这样做,因为 vector 迭代器是一个随机访问迭代器(在所有实现中,我知道它封装了一个指向原始容器数据的实际指针)。

【讨论】:

  • 在许多调试版本(例如 MSVC)中,vector&lt;T&gt;::iterator 也包含数组边界。这意味着它将在调试中捕获大多数越界错误。
  • @MSalters:是的,但我的意思是,它还包含指向原始序列(数组)的指针。
【解决方案4】:

您不能添加迭代器。

您将要使用std::distance()std::advance() 的组合:

vector<int>::iterator mid = std::advance(ivec.begin(), std::distance(ivec.begin(), ivec.end()) / 2);

为什么使用std::advance() 而不是迭代器的加法运算符? std::advance() 无论迭代器类型如何(随机访问、仅转发、双向等)都能以最佳方式工作,因此如果您从std::vector 切换到std::list,上述代码可以保持不变,并且仍能以最佳方式工作。

【讨论】:

  • 这不再是std::list 的最佳选择。在 C++11 中,std::distance(ilist.begin(), ilist.end()) 仍然可以是 O(N),但 ilist.size() 在 O(1) 中返回相同的值。
  • @MSalters:有趣!为什么会发生变化?
  • C++03 允许两者,在splice 上进行必要的权衡。因此,可移植代码必须将 sizesplice 都视为 O(N)。 C++11 使 size 可移植 O(1)。
【解决方案5】:

不能添加两个迭代器

使用at获取中间项:

ivec.at(ivec.size()/2);

【讨论】:

  • @Henrik:缺乏上下文。这将:cout &lt;&lt; ivec.at(ivec.size()/2) &lt;&lt; endl;。如果知道ivec不为空,也可以写cout &lt;&lt; ivec[ivec.size()/2] &lt;&lt; endl;
【解决方案6】:

你不能把两个迭代器加在一起,因为迭代器不是整数。这就是错误消息的含义。如果要访问向量中间的元素,请使用ivec[ivec.size() / 2]

【讨论】:

    猜你喜欢
    • 2011-02-15
    • 1970-01-01
    • 1970-01-01
    • 2014-06-24
    • 1970-01-01
    • 2021-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多