【问题标题】:Why STL requires a temporary iterator variable to compile this?为什么 STL 需要一个临时迭代器变量来编译它?
【发布时间】:2015-02-13 10:36:13
【问题描述】:

这是一段非常简单的代码:

#include <vector>

int main() {

    std::vector<int> myVec(5);
    std::vector<int>::const_iterator first = myVec.begin();
    std::vector<int>::const_iterator last = myVec.begin() + 3;
    std::vector<int> newVec1(first, last);
    std::vector<int> newVec2(myVec.begin(), last);

    return 0;
}

声明newVec1 的行编译。

声明newVec2 的行失败并出现以下错误:

prog.cpp: In function 'int main()':
prog.cpp:11:49: error: no matching function for call to 'std::vector<int>::vector(std::vector<int>::iterator, std::vector<int>::const_iterator&)'
     std::vector<int> newVec2(myVec.begin(), last);
                                                 ^
prog.cpp:11:49: note: candidates are:
In file included from /usr/include/c++/4.9/vector:64:0,
                 from prog.cpp:3:
/usr/include/c++/4.9/bits/stl_vector.h:401:9: note: template<class _InputIterator, class> std::vector<_Tp, _Alloc>::vector(_InputIterator, _InputIterator, const allocator_type&)
         vector(_InputIterator __first, _InputIterator __last,
         ^
/usr/include/c++/4.9/bits/stl_vector.h:401:9: note:   template argument deduction/substitution failed:
prog.cpp:11:49: note:   deduced conflicting types for parameter '_InputIterator' ('__gnu_cxx::__normal_iterator<int*, std::vector<int> >' and '__gnu_cxx::__normal_iterator<const int*, std::vector<int> >')
     std::vector<int> newVec2(myVec.begin(), last);
                                                 ^
In file included from /usr/include/c++/4.9/vector:64:0,
                 from prog.cpp:3:
/usr/include/c++/4.9/bits/stl_vector.h:373:7: note: std::vector<_Tp, _Alloc>::vector(std::initializer_list<_Tp>, const allocator_type&) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<int>]
       vector(initializer_list<value_type> __l,
       ^
/usr/include/c++/4.9/bits/stl_vector.h:373:7: note:   no known conversion for argument 1 from 'std::vector<int>::iterator {aka __gnu_cxx::__normal_iterator<int*, std::vector<int> >}' to 'std::initializer_list<int>'
/usr/include/c++/4.9/bits/stl_vector.h:348:7: note: std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>&&, const allocator_type&) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<int>]
       vector(vector&& __rv, const allocator_type& __m)
       ^
/usr/include/c++/4.9/bits/stl_vector.h:348:7: note:   no known conversion for argument 1 from 'std::vector<int>::iterator {aka __gnu_cxx::__normal_iterator<int*, std::vector<int> >}' to 'std::vector<int>&&'
/usr/include/c++/4.9/bits/stl_vector.h:339:7: note: std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&, const allocator_type&) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<int>]
       vector(const vector& __x, const allocator_type& __a)
       ^
/usr/include/c++/4.9/bits/stl_vector.h:339:7: note:   no known conversion for argument 1 from 'std::vector<int>::iterator {aka __gnu_cxx::__normal_iterator<int*, std::vector<int> >}' to 'const std::vector<int>&'
/usr/include/c++/4.9/bits/stl_vector.h:335:7: note: std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>&&) [with _Tp = int; _Alloc = std::allocator<int>]
       vector(vector&& __x) noexcept
       ^
/usr/include/c++/4.9/bits/stl_vector.h:335:7: note:   candidate expects 1 argument, 2 provided
/usr/include/c++/4.9/bits/stl_vector.h:318:7: note: std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = int; _Alloc = std::allocator<int>]
       vector(const vector& __x)
       ^
/usr/include/c++/4.9/bits/stl_vector.h:318:7: note:   candidate expects 1 argument, 2 provided
/usr/include/c++/4.9/bits/stl_vector.h:289:7: note: std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const value_type&, const allocator_type&) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::size_type = unsigned int; std::vector<_Tp, _Alloc>::value_type = int; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<int>]
       vector(size_type __n, const value_type& __value,
       ^
/usr/include/c++/4.9/bits/stl_vector.h:289:7: note:   no known conversion for argument 1 from 'std::vector<int>::iterator {aka __gnu_cxx::__normal_iterator<int*, std::vector<int> >}' to 'std::vector<int>::size_type {aka unsigned int}'
/usr/include/c++/4.9/bits/stl_vector.h:277:7: note: std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const allocator_type&) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::size_type = unsigned int; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<int>]
       vector(size_type __n, const allocator_type& __a = allocator_type())
       ^
/usr/include/c++/4.9/bits/stl_vector.h:277:7: note:   no known conversion for argument 1 from 'std::vector<int>::iterator {aka __gnu_cxx::__normal_iterator<int*, std::vector<int> >}' to 'std::vector<int>::size_type {aka unsigned int}'
/usr/include/c++/4.9/bits/stl_vector.h:264:7: note: std::vector<_Tp, _Alloc>::vector(const allocator_type&) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<int>]
       vector(const allocator_type& __a) _GLIBCXX_NOEXCEPT
       ^
/usr/include/c++/4.9/bits/stl_vector.h:264:7: note:   candidate expects 1 argument, 2 provided
/usr/include/c++/4.9/bits/stl_vector.h:253:7: note: std::vector<_Tp, _Alloc>::vector() [with _Tp = int; _Alloc = std::allocator<int>]
       vector()
       ^
/usr/include/c++/4.9/bits/stl_vector.h:253:7: note:   candidate expects 0 arguments, 2 provided

g++ 和 Visual Studio 都无法编译,知道为什么吗? myVec.begin()first 相同...

【问题讨论】:

  • 错误信息是不言自明的,两个迭代器必须是相同的类型。在您的情况下,一个是 const_iterator,另一个不是
  • 不,不是。 first 是常量。
  • 我不会将错误消息称为不言自明,但所有位都确实存在。最相关的是“deduced conflicting types for parameter '_InputIterator' ('__gnu_cxx::__normal_iterator&lt;int*, std::vector&lt;int&gt; &gt;' and '__gnu_cxx::__normal_iterator&lt;const int*, std::vector&lt;int&gt; &gt;')”(比较int*const int*
  • 同意,当您知道问题所在时,您可以像经常一样分析和理解错误消息... ;-)
  • 你不够懒惰 ;) auto last = myVec.begin() + 3; 会奏效的。

标签: c++ stl iterator


【解决方案1】:

myVec.begin()first 不同。 firststd::vector&lt;int&gt;::const_iterator 类型,而 myVec.begin()std::vector&lt;int&gt;::iterator 类型。

如果你想要一个 const 迭代器,请使用 cbegin:

std::vector<int> newVec2(myVec.cbegin(), last);

【讨论】:

  • 好点,谢谢。我错过了这个细节,因为 'std::vector::const_iterator first = myVec.begin()' 自动将非 const 转换为 const...
  • 再说明:如果 std::vector 构造函数按值使用迭代器,则转换可能会自动发生。但是,您的代码等效于转换 std::vector::const_iterator & firstRef = myVec.begin();这将失败并显示相同的错误消息。
  • @IMil:构造函数确实按值获取迭代器。然而,问题是模板参数推导失败,因为编译器无法决定要实例化的迭代器类型。
【解决方案2】:

vec.begin()first 不同,因为它会返回一个迭代器,而不是 const_iterator

发生这种情况是因为拥有 const 或非 const 迭代器取决于您对容器的访问类型,而不是您希望对迭代器进行的用途,这也是创建代理的原因在类似数组的对象::operator[] 中分离读写操作的唯一方法,而不是仅仅依赖 const 或非 const 版本。

这只是 const 正确性概念显示其局限性的许多情况。

【讨论】:

    猜你喜欢
    • 2015-01-25
    • 1970-01-01
    • 2017-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-08
    • 2018-03-19
    • 2021-01-20
    相关资源
    最近更新 更多