从常量成员函数返回迭代器

时间:2015-06-01 21:13:27

标签: c++ c++11 g++ c++14

在以下代码中,为什么foo::func的返回类型为vector<int>::const_iterator而不是vector<int>::iterator,但我返回vector<int>::iterator的对象。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class foo
{
private:
  vector<int> ar;
public:
  foo()
  {
    ar.resize(10);
    iota(ar.begin(), ar.end(), 1);
  }
  auto func() const
  {
    return ar.begin() + 5;
  }
};

int main()
{
  foo x;
  cout<<boolalpha<<endl;
  auto it = x.func();
  cout<<is_same<decltype(it), vector<int>::iterator>::value<<endl;
  cout<<is_same<decltype(it), vector<int>::const_iterator>::value<<endl;
  return 0;
}

上述代码的输出是:

false
true

相反,如果我将foo::func()重新定义为

auto func()
{
    return ar.begin() + 5;
}

输出

true
false

为什么常量成员函数将返回类型更改为常量? 我是否应该删除const关键字以使返回类型为vector<int>::iterator,还是有其他方式?

4 个答案:

答案 0 :(得分:5)

声明为const的成员函数会影响this指针的类型。在func()内,this的类型为const foo*。因此,通过const this指针访问的所有成员类型本身都是const,因此ar的隐式类型实际上是const std::vector<int>。在vector的两个begin()重载中,唯一可行的重载是const重载,它会返回const_iterator

当您将func()重新定义为非const时,this的类型只是foo*,因此成员ar的类型是std::vector<int>以及begin()返回iterator的重载是首选。

答案 1 :(得分:4)

There are two const取决于实例是否为foo::func() const

ar,您正在尝试访问const std::vector<int>,然后将其视为std::vector::begin() constconst_iterator返回ar

当您访问foo::func()中的std::vector<int>时,会将其视为const,而不会beginstd::vector::begin()将会引用const (再次没有foo),这不是同一个函数。

同样,您自己的foo::func类可以同时定义两个版本的auto func() { return ar.begin() + 5; } auto func() const { return ar.begin() + 5; }

foo x;
const foo y;

x.func();    // First version, get an iterator
y.func();    // Second version, get a const_iterator

实例的常量将决定调用哪个版本:

grep -ril "Omega" --exclude='<p> | <a href="www.omega.com"> Omega</a> |</p>' --exclude='<li><a href ="www.omega.com"> Omega</a></li>'

答案 2 :(得分:2)

iterator指向其中一个数据成员,因此如果函数为const,那么iterator也必须为const,否则您可能会更改其中包含的数据来自class成员函数返回的iterator的{​​{1}}。

这至少是我的理解 - 如果其他人能够证实或否认这一点,我将不胜感激。

答案 3 :(得分:2)

成员函数begin按以下方式重载

iterator begin() noexcept;
const_iterator begin() const noexcept;

因此,使用限定符const声明的函数处理常量对象。这意味着,如果常量对象的数据成员未声明为mutable,则它们也是常量。在这种情况下,将为返回begin的数据成员ar调用第二个重载函数const_iterator

相关问题