【问题标题】:Understanding const references and non-const references to iterators in C++. Why can't I use a non-const reference to iterator in the print function?了解 C++ 中对迭代器的 const 引用和非 const 引用。为什么我不能在 print 函数中使用对迭代器的非常量引用?
【发布时间】:2015-07-23 00:24:27
【问题描述】:

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


以下代码无法编译。

#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 并尝试复习我的课程,但未能成功获得理解。

【问题讨论】:

    标签: c++ iterator constants


    【解决方案1】:

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

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

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

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

    您不能对临时对象进行左值引用,因此代码无法编译。该错误确切地说明了 - 您正在尝试使用临时初始化非常量引用:

    hello.cpp:21:33:错误:从 'std::deque::reverse_iterator {aka std::reverse_iterator > }'

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

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

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

    【讨论】:

    • 谢谢@Barry。我从课程中得到了这个代码。你能想出一个使用引用的原因吗(考虑到库按值传递迭代器)?
    • @Elyasin 可能有一个用例,但它肯定是非典型的。你必须想出一个令人信服的理由来使用引用。按值传递应该是您的默认设置。
    • @Elyasin 课程讲师可能误解了迭代器
    • @MattMcNabb 你说的太对了。我继续课程,似乎所有示例都遇到了错误。现在我了解到我必须能够区分较旧的 C++ 和 C++11(这不是课程的一部分)。太费时间了:-(
    猜你喜欢
    • 2016-04-15
    • 2016-11-26
    • 2018-07-10
    • 1970-01-01
    • 2016-06-25
    • 1970-01-01
    • 1970-01-01
    • 2020-10-27
    • 2011-05-03
    相关资源
    最近更新 更多