【问题标题】:Why can I update member variables in a const member function?为什么我可以更新 const 成员函数中的成员变量?
【发布时间】:2020-04-23 03:37:55
【问题描述】:

我正在尝试实现一个类似于在 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 迭代器,您永远无法更新迭代器的内容。

如果我应该在代码 sn-p 中包含任何内容,请告诉我,谢谢!

【问题讨论】:

  • 我试了一下here,得到了错误“错误:无法分配给const成员函数'operator++'中的非静态数据成员”。

标签: c++ linked-list stl iterator doubly-linked-list


【解决方案1】:

在实例化模板函数之前,实际上不会检查错误。如果你不给他们打电话,他们只是坐在那里不被注意,炸弹等着引爆。添加对Iterator::operator++() const 的调用后,您将收到编译器错误。

比如我加了:

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

现在 clang 抱怨:

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 类。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-11
    • 1970-01-01
    • 1970-01-01
    • 2020-09-29
    • 1970-01-01
    • 1970-01-01
    • 2015-06-03
    相关资源
    最近更新 更多