C++ 如果容器元素是指针,为什么允许我从常量迭代器调用非常量成员函数?

C++ 如果容器元素是指针,为什么允许我从常量迭代器调用非常量成员函数?,c++,iterator,constants,C++,Iterator,Constants,考虑以下代码: #include <vector> using namespace std; struct foo { void bar() { } }; int main() { { vector<foo*> a; a.push_back(new foo()); a.push_back(new foo()); a.push_back(new foo()); vector<foo*>::const_

考虑以下代码:

#include <vector>
using namespace std;

struct foo
{
  void bar()
  {
  }
};

int main()
{
  {
    vector<foo*> a;
    a.push_back(new foo());
    a.push_back(new foo());
    a.push_back(new foo());

    vector<foo*>::const_iterator itr = a.begin();
    (*itr)->bar(); // compiles - this becomes more confusing 
                   // when found in a const method. On first 
                   // glance, one will (or at least me) may
                   // assume that bar() must be const if the 
                   // method where it is being called from is 
                   // const

    // The above compiles because internally, this is what happens 
    // (ignore the fact that the pointer has not been newd)
    foo* const * element;
    (*element)->bar(); // compiles

    // What I would expect however (maybe it is just me) is for const_iterator
    // to  behave something like this
    const foo* const_element;
    const_element->bar(); // compile error
  }

  {
    vector<foo> a;
    a.resize(10);

    vector<foo>::const_iterator itr = a.begin();
    itr->bar(); // compile error
  }

}
#包括
使用名称空间std;
结构foo
{
空条()
{
}
};
int main()
{
{
载体a;
a、 向后推(新的foo());
a、 向后推(新的foo());
a、 向后推(新的foo());
vector::const_迭代器itr=a.begin();
(*itr)->bar();//编译-这会变得更加混乱
//当在常量方法中找到时。在第一个
//看一眼,你会(或至少是我)知道的
//如果
//从中调用它的方法是
//常数
//上面的编译是因为内部会发生这种情况
//(忽略指针尚未更新的事实)
foo*const*元素;
(*元素)->bar();//编译
//然而,我所期望的(可能只是我)是常量迭代器
//做这样的事
const foo*const_uu元素;
const_元素->bar();//编译错误
}
{
载体a;
a、 调整大小(10);
vector::const_迭代器itr=a.begin();
itr->bar();//编译错误
}
}
我明白为什么可以叫它。
const\u迭代器
存储的常量如下:
const T*
指针的常量转换为
foo*const*
,对象的常量转换为
foo*const*

所以我的问题是,为什么我们可以从
常量迭代器
调用非常量成员函数?不允许从
常量迭代器调用非常量成员函数不是更直观吗?带有const选项的
迭代器的设计不应该阻止这种行为吗

现在更重要的问题是:如果我希望
常量迭代器
不允许调用指向对象的非常量成员函数,该怎么办?

带const选项的迭代器的设计不应该阻止这种行为吗

是的。你只是希望这是一次不同的手术

正如您所发现的,一个指针容器。。。包含指针,而不是对象。因此,指向此类指针的
常量迭代器
意味着指针是常量,而不是它们指向的对象

这不会改变,也不应该改变。标准库容器通常设计为包含完整的对象,而不是指针。因此,他们不应该鼓励用户使用指针和其他可疑的结构


如果您确实需要一个
向量
来包含指针,那么您应该使用一个实际设计用于此目的的容器。喜欢它们的
const_迭代器
可以正确地将对象指向
const
。它们还可以做其他有用的事情,比如拥有它们指向的对象(以便它们被正确删除)等等。

你有一个指针向量,指针没有成员函数,所以你没有对存储在向量中的对象调用成员函数

取消引用指针时获得的对象类型取决于该指针的类型。您的向量是非常量指针的向量,因此当您从容器中解除任何指针的限制时,始终会得到指向指向对象的非常量引用

如果你想要一个指针向量,那么你有两个选择。您可以创建一个
向量
,这样您将永远无法检索到指向对象或,如果需要能够从向量的非常量实例中获取非常量引用,则必须创建一个对象,该对象包含作为私有成员变量的向量,并通过传递接口为您提供所需的访问权限

如果您的向量应该拥有它所持有的指针,则可以考虑简单的<代码>向量< /代码>,或者,如果需要动态分配,则<代码> Booo::pTrvector vector < /COL>

所以我的问题是,为什么我们可以从常量迭代器调用非常量成员函数

“常量迭代器”表示容器元素是常量。这并不意味着如果该元素是指针,则指向的对象也是常量

如果我希望常量迭代器不允许调用指向对象的非常量成员函数,该怎么办

我不想鼓励您使用像这样的原始指针,但如果您真的必须这样做,请将其作为指向常量对象的指针容器

std::vector<const foo*> a;
// ...
auto itr = a.cbegin();
(*itr)->bar(); // Compiler error (calling a non-const method on const object).
std::向量a;
// ...
自动itr=a.cbegin();
(*itr)->bar();//编译器错误(在常量对象上调用非常量方法)。
当然,在这种情况下,也不允许出现以下情况:

std::vector<const foo*> a;
// ...
auto itr = a.begin();
(*itr)->bar(); // Compiler error.
std::向量a;
// ...
自动itr=a.begin();
(*itr)->bar();//编译器错误。