从常量成员函数返回迭代器
Returning iterator from constant member function
在下面的代码中,为什么 foo::func
的 return 类型是 vector<int>::const_iterator
而不是 vector<int>::iterator
尽管我 return 是 [=] 的对象16=].
#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
为什么常量成员函数正在将 return 类型更改为常量?
我是否需要删除 const
关键字以使 return 类型成为 vector<int>::iterator
还是有其他方法?
iterator
指向它的数据成员之一,所以如果函数是 const
那么 iterator
也必须是 const
否则你可以改变数据包含在由 const
成员函数返回的 iterator
中的 class
中。
至少这是我的理解 - 如果其他人可以证实或否认这一点,我将不胜感激。
There are two std::vector::begin
取决于实例是否 const
。
在 foo::func() const
中,您正在尝试访问 ar
,然后将其视为 const std::vector<int>
,并且 std::vector::begin() const
returns const_iterator
.
当您在 foo::func()
中访问 ar
时,它将被视为 std::vector<int>
,而不是 const
,然后 begin
将引用 std::vector::begin()
(又没有const
),这不是同一个函数。
同样,您自己的 foo
class 可以同时定义 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
const
声明的成员函数会影响 this
指针的类型。在 func()
中,this
的类型为 const foo*
。因此,通过 const
this
指针访问的所有成员类型本身都是 const
,因此 ar
的隐式类型实际上是 const std::vector<int>
。在 vector
的两个 begin()
重载中,唯一可行的重载是 const
重载,returns 一个 const_iterator
.
当你重新定义 func()
为非 const
时,this
的类型就是 foo*
,所以成员的类型 ar
是 std::vector<int>
并且 begin()
的重载返回 iterator
是首选。
成员函数begin
重载方式如下
iterator begin() noexcept;
const_iterator begin() const noexcept;
因此,使用限定符 const
声明的函数处理常量对象。这意味着常量对象的数据成员如果未声明为 mutable
也是常量。在这种情况下,为 returns const_iterator
.
的数据成员 ar
调用第二个重载函数 begin
在下面的代码中,为什么 foo::func
的 return 类型是 vector<int>::const_iterator
而不是 vector<int>::iterator
尽管我 return 是 [=] 的对象16=].
#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
为什么常量成员函数正在将 return 类型更改为常量?
我是否需要删除 const
关键字以使 return 类型成为 vector<int>::iterator
还是有其他方法?
iterator
指向它的数据成员之一,所以如果函数是 const
那么 iterator
也必须是 const
否则你可以改变数据包含在由 const
成员函数返回的 iterator
中的 class
中。
至少这是我的理解 - 如果其他人可以证实或否认这一点,我将不胜感激。
There are two std::vector::begin
取决于实例是否 const
。
在 foo::func() const
中,您正在尝试访问 ar
,然后将其视为 const std::vector<int>
,并且 std::vector::begin() const
returns const_iterator
.
当您在 foo::func()
中访问 ar
时,它将被视为 std::vector<int>
,而不是 const
,然后 begin
将引用 std::vector::begin()
(又没有const
),这不是同一个函数。
同样,您自己的 foo
class 可以同时定义 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
const
声明的成员函数会影响 this
指针的类型。在 func()
中,this
的类型为 const foo*
。因此,通过 const
this
指针访问的所有成员类型本身都是 const
,因此 ar
的隐式类型实际上是 const std::vector<int>
。在 vector
的两个 begin()
重载中,唯一可行的重载是 const
重载,returns 一个 const_iterator
.
当你重新定义 func()
为非 const
时,this
的类型就是 foo*
,所以成员的类型 ar
是 std::vector<int>
并且 begin()
的重载返回 iterator
是首选。
成员函数begin
重载方式如下
iterator begin() noexcept;
const_iterator begin() const noexcept;
因此,使用限定符 const
声明的函数处理常量对象。这意味着常量对象的数据成员如果未声明为 mutable
也是常量。在这种情况下,为 returns const_iterator
.
ar
调用第二个重载函数 begin