【问题标题】:Own iterator crashed with std::sort自己的迭代器因 std::sort 而崩溃
【发布时间】:2017-01-14 16:00:34
【问题描述】:

我正在尝试开发智能迭代器,但即使我创建了一个幼稚的迭代器,当我使用排序时它也会崩溃。

for 循环的范围运行良好,但 std::sort 不行。

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

template<typename I>
class it {
public:
    it(I i) : i(i){}
    using iterator_category = std::random_access_iterator_tag;
    using value_type = typename I::value_type;
    using difference_type = std::ptrdiff_t;
    using pointer = typename I::pointer;
    using reference = typename I::reference;
    value_type &operator*() {
        return *i;
    }

    it &operator++() {
        ++i;
        return *this;
    }

    it &operator--() {
        --i;
        return *this;
    }

    bool operator!=(it a) {
        return a.i != i;
    }

    it &operator+(std::size_t n) {
        i += n;
        return *this;
    }

    it &operator-(std::size_t n) {
        i -= n;
        return *this;
    }

    std::ptrdiff_t operator-(it a) {
        return i - a.i;
    }

    bool operator==(it a) {
        return a.i == i;
    }

    bool operator<(it a) {
        return i < a.i;
    }

private:
    I i;
};

int main()
{
    std::vector<int> v = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};

    for(auto e : v)
        std::cout << e << " ";
    std::cout << std::endl;

    std::sort(it<decltype(v.begin())>(v.begin()), it<decltype(v.end())>(v.end()));

    for(auto e : v)
        std::cout << e << " ";
    std::cout << std::endl;

    return 0;
}

崩溃发生在此处的“clang-code”中(gdb 告诉我):

struct _Iter_less_iter
  {
    template<typename _Iterator1, typename _Iterator2>
      _GLIBCXX14_CONSTEXPR
      bool
      operator()(_Iterator1 __it1, _Iterator2 __it2) const
      { return *__it1 < *__it2; }
  };

它是在它尊重它时发生的。 你有什么想法吗?

【问题讨论】:

    标签: c++ c++11 iterator


    【解决方案1】:

    不确定根本问题是什么,但这绝对是错误的:

    it &operator+(std::size_t n) {
            i += n;
            return *this;
        }
    

    那个操作符应该返回一个 new 迭代器,而不是修改它被调用的那个。像这样的:

    it operator+(std::size_t n) {
            it temp = *this;
            temp.i += n;
            return temp;
        }
    

    请注意,这按值返回迭代器,而不是按引用。

    operator- 也是如此。

    【讨论】:

    • 不要觉得自己很愚蠢。在迭代器中很容易迷失方向。
    • 更多是因为我没有使用好的原型运算符+^^。但是是的,迭代器并不那么容易
    【解决方案2】:

    您的operator+ 具有operator+= 的语义,而您的operator- 具有operator-= 的语义。他们不应该修改迭代器,而是用修改后的值创建一个新的迭代器并返回它。此外,它们都应该接受带符号的值。事实上,一个合适的随机访问迭代器应该有两组操作符,所以保持函数不变,但改变签名。

    it& operator+=(difference_type n) {
        i += n;
        return *this;
    }
    
    it &operator-=(difference_type n) {
        i -= n;
        return *this;
    }
    

    然后您可以根据这些实现operator+operator-。 (注意这些是按值返回,而不是引用,并且标记为 const)

    it operator+(difference_type n) const {
        it result = *this;
        result += n;
        return result;
    }
    
    it operator-(difference_type n) const {
        it result = *this;
        result -= n;
        return result;
    }
    

    【讨论】:

    • 感谢您的详细信息:)
    猜你喜欢
    • 1970-01-01
    • 2016-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-31
    • 1970-01-01
    • 2012-12-10
    • 2019-11-29
    相关资源
    最近更新 更多