为什么要在const成员函数中更新成员变量?

问题描述 投票:1回答:1

我正在尝试实现一个链表,类似于它在STL中的实现方式。在实现迭代器时,我制作了一些const成员函数(以便用户可以使用const迭代器),并注意到我能够更新成员变量而不会出现编译器错误。该代码使用模板,但是我测试了它调用了一个使用begin()并带有const列表的函数,因此我知道修改成员变量的模板函数是由编译器生成的。有谁知道为什么这样吗?有问题的函数是operator ++的const版本。

这是我程序的一个版本,其中删除了无关的详细信息。

template<typename E>
struct Link {
    E val {};
    Link* next = nullptr;
    Link* prev = nullptr;
};

template<typename E>
struct List {   
    struct Iterator {
        Iterator(Link<E>* c) : curr{c} { }

        Iterator& operator++();
        const Iterator& operator++() const;

        const E& operator*() const {return curr->val;}
        E& operator*() {return curr->val;}

        // ...
    private:
        Link<E>* curr;
    };

    // Constructors, etc ...
    // Operations ...

    E& front() {return head->val;}
    const E& front() const {return head->val;}

    Iterator begin() {return Iterator{head};}
    const Iterator begin() const {return Iterator{head};}
    // Other iterator stuff ...

private:
    Link<E>* head;
    Link<E>* tail;
    int sz;
};

/*---------------------------------------------*/

template<typename E>
typename List<E>::Iterator& List<E>::Iterator::operator++() {
    curr = curr->next;
    return *this;
}

template<typename E>
const typename List<E>::Iterator& 
        List<E>::Iterator::operator++() const
{
    curr = curr->next;
    return *this;
}

我从概念上讲,即使它修改了成员变量,也要使它成为const版本的operator ++是有意义的。 const迭代器实际上将Link指针的内容称为const,这正是为什么它在解引用运算符中返回const E&的原因。因此,使用const迭代器,您将永远无法更新迭代器的内容。

让我知道代码段中应该包含什么内容,谢谢!

c++ linked-list stl iterator doubly-linked-list
1个回答
2
投票

模板函数在实例化之前实际上不会检查错误。如果您不打电话给他们,他们只是不经意地坐在那里,炸弹正等着熄灭。将调用添加到Iterator::operator++() const后,会出现编译器错误。

例如,我添加了:

int main() {
    List<int> list;
    const List<int>::Iterator iter = list.begin();
    ++iter;
}

现在叮当声抱怨:

main.cpp:52:10: error: cannot assign to non-static data member within const
      member function 'operator++'
    curr = curr->next;
    ~~~~ ^
main.cpp:61:3: note: in instantiation of member function
      'List<int>::Iterator::operator++' requested here
  ++iter;
  ^
main.cpp:14:25: note: member function 'List<int>::Iterator::operator++' is
      declared const here
        const Iterator& operator++() const;
                        ^

([Repl


我从概念上讲,即使它修改了成员变量,也要使它成为const版本的operator ++是有意义的。 const迭代器实际上将Link指针的内容称为const,这正是为什么它在解引用运算符中返回const E&的原因。因此,使用const迭代器,您将永远无法更新迭代器的内容。

const迭代器不应是可变的,也不应具有++运算符。 STL实际上具有单独的iteratorconst_iterator类型。 const_iterator体现了您所描述的概念:迭代器本身是可变的,但其指向的却是const

我建议您遵循并创建一个单独的ConstIterator类。

© www.soinside.com 2019 - 2024. All rights reserved.