为什么会出现以下错误:“返回对临时[-Werror = return-local-addr]的引用”

时间:2018-06-26 15:02:58

标签: c++ class c++11 return-by-reference

给出以下代码:

#include <set>

using std::set;

class Pool {
    set<int> s;
public:   
    typedef typename set<int>::iterator Iterator;
    const Iterator& begin() const {
      return s.begin(); //** error
    }
};    

为什么会出现以下错误(我理解该错误的含义,但是,在这种情况下,我不明白为什么会得到它)?

  

返回对临时[-Werror = return-local-addr]的引用

我该如何解决?

2 个答案:

答案 0 :(得分:3)

set<...>::begin函数通过值返回其迭代器 。由于您不会在任何地方存储该值,因此它是一个临时值,并且您实际上无法引用临时值。

简单的解决方案是您的函数还 通过(非const)值返回。

答案 1 :(得分:1)

const Iterator& begin() const {
  return s.begin(); //** error
}

是非法的,因为s.begin()的结果是一个临时对象,因此您不能返回对其的引用。也许如果您看一下等效的代码,它会更清楚吗?

const Iterator& begin() const {
  Iterator it = s.begin();
  return it; //** error
}

将const引用返回给迭代器并没有多大意义,因为您将无法移动迭代器指向的位置。您应该始终按值返回迭代器,这样,调用方就可以自由制作迭代器的副本并修改其位置。例如,如果您可以让您的代码编译以下调用代码,则将不起作用:

Pool p;
const Pool::Iterator& it = p.begin();
++it; //error it is constant

用户可以通过将您返回的引用复制到新对象中来修复其代码:

Pool p;
Pool::Iterator it = p.begin();
++it; //no error

由于您的用户将无法使用引用,因此仅返回值就无法返回更好的引用:

const Iterator begin() const {
  return s.begin();
}

请注意,std::set与大多数其他容器不同,并且不允许通过其迭代器修改值:https://en.cppreference.com/w/cpp/container/set/begin

  

因为迭代器和const_iterator都是常量迭代器(实际上可能是相同的类型),所以不可能通过这些成员函数中的任何一个返回的迭代器来对容器的元素进行突变。