理解C ++中对const迭代器的const引用和非const引用。为什么我不能在print函数中对迭代器使用非const引用?

时间:2015-07-23 00:24:27

标签: c++ iterator const

有人可以向我解释一下C ++中const iterator引用和non-const iterator引用之间的区别吗? 为什么我无法在non-const iterator函数中使用print引用?

以下代码无法编译。

#include <deque>
#include <iostream>

using namespace std;

template<typename T> ostream & print(T & start, T & end) {
    for (; start != end; ++start) {
        cout << *start << " ";
    }
    return cout;
}

int main() {
    int tab[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    deque<int> d1(tab, tab + 10);
    deque<int> d2;
    deque<int>::iterator it;
    for (it = d1.begin(); it != d1.end(); ++it) {
        d2.push_back(d1[d1.end() - it - 1]); //LINE I
    }
    print(d2.rbegin(), d2.rend()) << endl; //LINE II
    return 0;
}

错误信息对我来说有点神秘。

hello.cpp:21:33: error: invalid initialization of non-const reference of type ‘std::reverse_iterator<std::_Deque_iterator<int, int&, int*> >&’ from an rvalue of type ‘std::deque<int>::reverse_iterator {aka std::reverse_iterator<std::_Deque_iterator<int, int&, int*> >}’
     print(d2.rbegin(), d2.rend()) << endl; //LINE II
                                 ^
hello.cpp:6:32: error: in passing argument 1 of ‘std::ostream& print(T&, T&) [with T = std::reverse_iterator<std::_Deque_iterator<int, int&, int*> >; std::ostream = std::basic_ostream<char>]’
 template<typename T> ostream & print(T & start, T & end) {

我设法更改代码(基于另一个代码示例)以使其工作。

#include <deque>
#include <iostream>

using namespace std;

template<typename T> ostream & print(const T & start, const T & end) {
    T tmp = start;
    for (; tmp != end; ++tmp) {
        cout << *tmp << " ";
    }
    return cout;
}

int main() {
    int tab[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    deque<int> d1(tab, tab + 10);
    deque<int> d2;
    deque<int>::iterator it;
    for (it = d1.begin(); it != d1.end(); ++it) {
        d2.push_back(d1[d1.end() - it - 1]); //LINE I
    }
    print(d2.rbegin(), d2.rend()) << endl; //LINE II
    return 0;
}

我得到了一个结果。

1 2 3 4 5 6 7 8 9 10 

我认为差异是const iterator引用和non-const iterator引用的声明。但我不明白为什么。我检查了C++ Reference,我试图回顾我的课程,但我没有成功获得理解。

1 个答案:

答案 0 :(得分:6)

这与const和非const迭代器无关。在这一行:

print(d2.rbegin(), d2.rend()) << endl;

rbegin()rend()返回reverse_iterator类型的临时对象。另一方面,print()采用左值引用:

template<typename T> ostream & print(T & start, T & end);

你不能对一个临时值进行左值引用,因此代码无法编译。错误恰恰说明了 - 您正在尝试使用临时函数初始化非const引用:

  

hello.cpp:21:33:错误:从'std :: deque :: reverse_iterator {aka std ::'类型的右值开始,无效初始化类型'std :: reverse_iterator&gt;&amp;'的非const引用reverse_iterator&gt;}'

可以使用临时初始化 const 引用,这就是你的修复工作的原因。但实际上,你根本不需要参考。只需编写print()以按值获取其迭代器:

template<typename T>
ostream & print(T start, T end) {
    for (; start != end; ++start) {
        cout << *start << " ";
    }
    return cout;
}

整个标准库算法套件都是这样做的。像标准库那样做。