【问题标题】:c++: const_iterator and the for-each loopc++: const_iterator 和 for-each 循环
【发布时间】:2014-03-24 18:15:03
【问题描述】:

我正在用 C++ 制作自己的 Vector 实现。这是一个两部分的问题。

第 1 部分:尝试遍历 Vector 时,我的 begin() 和 end() 迭代器无法处理输入参数。下面是我的整个 Vector.h 实现:

    class iterator{
    public:

        typedef std::random_access_iterator_tag iterator_category;
        typedef T value_type;

        Vector<T>* ptr;
        uint64_t position;
        COMLINK slave;

        void init(void){
            ptr = nullptr;
            position = 0;
        }
        void copy(const iterator& i){
            init();
            ptr = i.ptr;
            position = i.position;
            slave = i.slave;
        }
        void move(iterator&& i){
            init();
            std::swap(ptr, i.ptr);
            std::swap(position, i.position);
            std::swap(slave, i.slave);
        }

        iterator(void){
            init();
        }
        iterator(const iterator& q){
            copy(q);
        }
        explicit iterator(Vector<T>* v, uint64_t offset){
            init();
            ptr = v;
            position = offset;
            slave = v->master;
        }
        T& operator*(void){
            if ((position >= ptr->len) || ((ptr->buffer + position) < ptr->elem))throw invalid_iterator(invalid_iterator::SEVERE);
            else if (slave.move_cnt != ptr->master.move_cnt) throw invalid_iterator(invalid_iterator::MODERATE);
            else if (slave.alter_cnt != ptr->master.alter_cnt) throw invalid_iterator(invalid_iterator::MILD);
            else if (slave.position_cnt != ptr->master.position_cnt) throw invalid_iterator(invalid_iterator::WARNING);
            return *(ptr->elem + position);
        }
        bool operator==(const iterator& rhs){
            return (ptr == rhs.ptr) && (position == rhs.position) && (slave == rhs.slave);
        }
        bool operator!=(const iterator& rhs){
            return !((*this) == rhs);
        }
        iterator& operator=(const iterator& rhs){
            copy(rhs);
            return *this;
        }
        iterator& operator++(void){
            position++;
            return *this;
        }
        iterator& operator--(void){
            position--;
            return *this;
        }
        iterator operator+(uint64_t i){ // p + i
            iterator temp(*this);
            temp.position += i;
            return temp;
        }
        iterator operator-(uint64_t i){ // p - i
            iterator temp(*this);
            temp.position -= i;
            return temp;
        }
        uint64_t operator-(const iterator& q){
            return position - q.position;
        }
    };

    class const_iterator : public iterator {
    public:
        Vector<T>* const ptr;

        void init(void){
            ptr = nullptr;
            position = 0;
        }
        void copy(const_iterator& i){
            init();
            ptr = i.ptr;
            position = i.position;
            slave = i.slave;
        }
        void copy(iterator& i){
            init();
            ptr = i.ptr;
            position = i.position;
            slave = i.slave;
        }
        void move(const_iterator&& i){
            init();
            std::swap(ptr, i.ptr);
            std::swap(position, i.position);
            std::swap(slave, i.slave);
        }
        void move(iterator&& i){
            init();
            std::swap(ptr, i.ptr);
            std::swap(position, i.position);
            std::swap(slave, i.slave);
        }

        const_iterator(void){
            init();
        }
        const_iterator(const_iterator& i){
            copy(i);
        }
        explicit const_iterator(Vector<T>* const v, uint64_t offset){
            init();
            ptr = v;
            position = offset;
            slave = v->master;
        }
        const_iterator(iterator& i){
            copy(i);
        }
        const T& operator*(void){
            if ((position >= ptr->len) || ((ptr->buffer + position) < ptr->elem))throw invalid_iterator(invalid_iterator::SEVERE);
            else if (slave.move_cnt != ptr->master.move_cnt) throw invalid_iterator(invalid_iterator::MODERATE);
            else if (slave.alter_cnt != ptr->master.alter_cnt) throw invalid_iterator(invalid_iterator::MILD);
            else if (slave.position_cnt != ptr->master.position_cnt) throw invalid_iterator(invalid_iterator::WARNING);
            return *(ptr->elem + position);
        }
        const_iterator& operator=(iterator& i){
            copy(i);
            return *this;
        }
    };

这些是向量中的 beign() 和 end() 函数:

    iterator& begin(){
        return iterator(this, 0);
    }

    const_iterator& begin() const{
        return const_iterator(this, 0);
    }

    iterator& end(){
        return iterator(this, len);
    }

    const_iterator& end() const{
        return const_iterator(this, len);
    }

最后......最后(抱歉,长度)......这是触发编译错误的测试代码:

const Vector<int32_t>& y = x;
int32_t s = 0;
for (const auto& v : y) {
    s += v;
}

我收到的错误是:

Warning 3   warning C4172: returning address of local variable or temporary c:\users\alexander\documents\visual studio 2013\projects\vectorcontainerphasec_debug\vector.h   319 1   VectorContainerPhaseC_Debug
Error   4   error C2665: 'epl::Vector<int>::const_iterator::const_iterator' : none of the 4 overloads could convert all the argument types  c:\users\alexander\documents\visual studio 2013\projects\vectorcontainerphasec_debug\vector.h   323 1   VectorContainerPhaseC_Debug

我已经研究这个问题几个小时,但找不到解决方案。有什么建议吗?

第 2 部分:除了我上面所做的之外,还有其他方法可以实现 const_iterator 吗?对我来说,将这么多的函数从迭代器重新定义为 const_iterator 似乎是多余的。我什至需要创建一个 const_iterator 类吗?

【问题讨论】:

  • 你有一个const 对象,并且你试图将一个指向它的指针传递给一个指向一个非常量对象的指针。
  • 为什么你的 beginend 函数通过引用返回?
  • 我认为你的问题在于你有Vector&lt;T&gt;* const:我认为你需要的实际上是const Vector&lt;T&gt; *。第一个说“指向 Vector 的常量指针”,而第二个说“指向 Vector 常量的指针”(或者“指向常量 Vector 的指针”)。更一般地说,如果你有 const T * p,那么你可以更改 what i> p 指向 to,但不修改该值(不能修改 *p;如果你有 T * const q,那么你不能更改 q指向,但您可以更改该值(有点像参考)。
  • const_iterator 派生自iterator 对我来说似乎是错误的,这意味着 const_iterator 可以隐式转换为迭代器。此外,您的对象中最终会出现两个ptr。您缺少许多 typedef 和函数来使其成为有效的迭代器。 Boost 有帮助创建迭代器,而无需自己编写太多重复的东西。
  • 关于警告 C4172:您的 beginend 方法返回悬空引用。去掉&amp;,按值返回。

标签: c++ vector foreach-loop-container const-iterator


【解决方案1】:

您可能希望您的const_iterator 指向const Vector。您还需要调整构造函数,如下所示:

class const_iterator : public iterator {
public:
    const Vector<T>* const ptr;

    ...
    explicit const_iterator(const Vector<T>* v, uint64_t offset){
        ...
    }

这样,您的 const_iterator 构造函数应该可以在您的迭代范围内调用。
如果您需要了解 const 关键字在指针声明中如何工作的详细信息,请参阅 Difference between const declarations in C++

【讨论】:

  • 谢谢马丁,我对常量声明的理解肯定是不正确的
猜你喜欢
  • 2015-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-15
  • 2012-10-11
  • 1970-01-01
  • 1970-01-01
  • 2012-08-06
相关资源
最近更新 更多