在以下代码中,为什么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
,还是有其他方式?
答案 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() const
,const_iterator
返回ar
。
当您访问foo::func()
中的std::vector<int>
时,会将其视为const
,而不会begin
,std::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
。