简体   繁体   English

如果容器元素是指针,为什么我允许从const_iterator调用非const成员函数?

[英]Why am I allowed to call a non-const member function from a const_iterator if the container element is a pointer?

Consider the following code: 请考虑以下代码:

#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
  }

}

I understand why it can be called. 我理解为什么可以这样称呼它。 The const_iterator stores the const-ness like this: const T* which for the pointer translates to foo* const * and for the object foo const * . const_iterator存储const-ness,如下所示: const T* ,指针转换为foo* const * ,对象为foo const *

So my question is, why are we allowed to call a non-const member function from a const_iterator ? 所以我的问题是,为什么我们允许从const_iterator调用非const成员函数? Isn't it more intuitive to not allow the call to a non-const member function from a const_iterator ? 不允许从const_iterator调用非const成员函数更直观吗? Shouldn't the design of iterator s with the const option prevent this behaviour? 不应该使用const选项设计iterator防止这种行为吗?

The more important question now is this: What if I want const_iterator to disallow calling of non-const member functions of the pointed to object? 现在更重要的问题是: 如果我希望const_iterator禁止调用指向对象的非const成员函数,该怎么办?

Shouldn't the design of iterators with the const option prevent this behaviour? 不应该使用const选项设计迭代器来防止这种行为吗?

It does. 确实如此。 You're just expecting it to be a different operation. 你只是期望它是一个不同的操作。

As you discovered, a container of pointers... contains pointers , not objects. 正如您所发现的,指针容器......包含指针 ,而不是对象。 Therefore, a const_iterator to such pointers means that the pointers are constant, not the objects they point to. 因此,这样的指针的const_iterator意味着指针是常量,而不是它们指向的对象。

That's not going to change, nor should it. 这不会改变,也不会改变。 The standard library containers are generally designed to contain full-fledged objects, not pointers. 标准库容器通常设计为包含完整的对象,而不是指针。 So they shouldn't encourage users to make vector s of pointers and other dubious constructs. 所以他们不应该鼓励用户制作指针和其他可疑构造的vector

If you really need a vector to contain pointers, then you should use a container that is actually designed to do so. 如果你真的需要一个包含指针的vector ,那么你应该使用一个实际设计的容器。 Like Boost's pointer container classes . 就像Boost的指针容器类一样 Their const_iterators make the objects being pointed to const properly. 他们的const_iterators使对象正确地指向const They also do other useful things, like own the objects they point to (so that they are properly deleted) and so forth. 他们还做其他有用的事情,比如拥有他们指向的对象(以便正确删除它们)等等。

You have a vector of pointers, pointers don't have member functions so you're not calling a member function on something that is stored in the vector. 你有一个指针向量,指针没有成员函数,因此你不会在存储在向量中的东西上调用成员函数。

The type of object that you get when you dereference a pointer depends on the type of that pointer. 取消引用指针时获得的对象类型取决于该指针的类型。 Your vector is a vector of non-const pointers so when you derefence any pointer from your container you always get a non-const reference to the pointed to object. 您的向量是非常量指针的向量,因此当您从容器中解除任何指针时,您总是会获得对指向对象的非常量引用。

If you want a vector of pointers then you have two options. 如果你想要一个指针矢量,那么你有两个选择。 You can create a vector<const foo*> instead and you will never be able to retrieve a non-const reference to any pointer to object or, if you need to be able to get non-const references from non-const instances of your vector you will have to create an object that contains the vector as a private member variable and gives you the access that you want via a pass-through interface. 你可以创建一个vector<const foo*> ,你将永远无法检索对任何指向对象的指针的非const引用,或者,如果你需要能够从你的非const实例获得非const引用向量您必须创建一个包含向量作为私有成员变量的对象,并通过传递接口为您提供所需的访问权限。

If your vector is supposed to own the objects that it holds pointers to you could consider simple vector<foo> instead or, if dynamic allocation is required, a boost::ptr_vector<foo> . 如果你的向量应该拥有它保存指针的对象,你可以考虑使用简单的vector<foo>或者如果需要动态分配,则可以考虑使用boost::ptr_vector<foo>

So my question is, why are we allowed to call a non-const member function from a const_iterator? 所以我的问题是,为什么我们允许从const_iterator调用非const成员函数?

"Constant iterator" means container element is constant. “常量迭代器”表示容器元素是常量。 It doesn't mean that if that element is a pointer, the pointed object is also constant. 这并不意味着如果该元素是指针,则指向的对象也是常量。

What if I want const_iterator to disallow calling of non-const member functions of the pointed to object? 如果我希望const_iterator禁止调用指向对象的非const成员函数,该怎么办?

I wouldn't want to encourage you using raw pointers like this, but if you really have to, make it a container of pointers to const objects. 我不想鼓励你使用像这样的原始指针,但是如果你真的必须这样做,那就把它作为指向const对象的指针的容器。

std::vector<const foo*> a;
// ...
auto itr = a.cbegin();
(*itr)->bar(); // Compiler error (calling a non-const method on const object).

Of course, in that case the following would also be disallowed: 当然,在这种情况下,以下情况也是不允许的:

std::vector<const foo*> a;
// ...
auto itr = a.begin();
(*itr)->bar(); // Compiler error.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么我可以从 const 方法调用非常量成员函数指针? - Why can I call a non-const member function pointer from a const method? const成员函数中对此的非const指针 - Non-const pointer to this in const member function 从const成员函数调用非const成员函数 - Call a non-const member function from a const member function 在非const成员函数中,为什么指向此非const,而decltype指针则为const? - In a non-const member function, why is point this non-const, while decltype pointer this is const? 为什么我不能在 std::set 中的元素上调用非常量成员函数? - Why can't I call a non-const member function on an element in an std::set? 擦除获取const_iterator,但通过迭代器调用(非const) - erase gets const_iterator but is called with iterator (non-const) 算法不适用于非常量 object 的 const_iterator - Algorithm not working on const_iterator for non-const object 为什么指向非const成员函数的指针不能指向const成员函数而相反? - Why pointer to non-const member function can't point const member function and opposite? 解析 const 和 non-const 成员 function 指针 - Resolve const and non-const member function pointer MSVC:使用 const 和非常量重载推断指向成员函数的指针 - MSVC: inference of pointer to member function with const and non-const overloads
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM