我尝试使用自定义迭代器中的运算符*()返回值时出现以下错误。
error: invalid initialization of non-const reference of type 'char&' from a temporary of type 'char'
如果有人能够帮助我,那就太棒了!
代码的细节如下:
测试代码:
for(btree<char>::iterator itr = tree.begin(); itr != tree.end(); ++itr) {
cout << *itr << " "; // <- this line complains about the * operator.
}
运算符*()代码:
template <typename T> typename btree_iterator<T>::reference btree_iterator<T>::operator*() const {
return pointee_->value(); // <- this line is where the error above is produced from.
}
来自btree_iterator类的pointee_是一个私有变量,定义如下:
btree_node<T>* pointee_;
引用在btree_iterator类中键入以下内容:
typedef T& reference;
value()在btree_node类中定义如下:
T value() const;
// function definition.
template <typename T> T btree_node<T>::value() const { return value_; }
值最初通过它的构造函数存储到btree_node中,如下所示:
template <typename T> btree_node<T>::btree_node(const T& elem) : value_(elem), nextCont_(NULL), prevCont_(NULL), nextNode_(NULL), prevNode_(NULL) {}
如果我错过了包含任何重要信息,请告诉我,如果我做了就道歉!
基于错误,听起来我正在尝试返回对局部变量的引用。迭代器本身可能是本地的,但它返回的值不应该是,因为节点构造函数最初接受引用,并将其存储到节点中。
提前致谢,并致以问候!
答案 0 :(得分:3)
您正在尝试使用对临时变量的引用
template <typename T> T btree_node<T>::value() const { return value_; }
^^^
这将返回value_
的临时副本。
template <typename T> typename btree_iterator<T>::reference btree_iterator<T>::operator*() const {
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
return pointee_->value(); // <- this line is where the error above is produced from.
}
这将返回对该临时副本的引用。您最有可能希望value()
返回引用,但这取决于您 - 引用允许您btree
的客户端更改内容。特别是如果树是基于节点的值排序的,您可能不希望允许这样。想一想这与您的设计有什么关系。
答案 1 :(得分:1)
pointee_->value()
返回一个基本上是新副本的值。因此,此值在operator*
中是本地值,您无法返回对该值的引用。
我建议就像大多数容器一样,即同时拥有iterator
和const_iterator
,而const_iterator返回一个const引用,迭代器返回一个引用。同样的原则适用于value()
。有版本返回ref和const ref。
如果您想要处理副本,可以从客户端代码中的引用创建它们。如果您不想允许对值进行操作,只需删除(或使私有或其他)非const部分。它认为它也适合人们使用你的btree期望:
迭代器不会在某处复制,而是在数据结构内部的数据上进行迭代。如果你想要副本,你可以制作它们。