C++ stl容器中的常量和非常量

C++ stl容器中的常量和非常量,c++,boost,stl,C++,Boost,Stl,STL向量模板将元素访问器定义为常量和非常量变量,例如: reference operator[](size_type __n) {return *(this->_M_impl._M_start + __n);} const_reference operator[](size_type __n) const {return *(this->_M_impl._M_start + __n);} 编译器何时决定使用一个版本而不是另一个版本?向量本身没有定义为常量,其中

STL向量模板将元素访问器定义为常量和非常量变量,例如:

reference operator[](size_type __n) 
    {return *(this->_M_impl._M_start + __n);}
const_reference operator[](size_type __n) const 
    {return *(this->_M_impl._M_start + __n);}
编译器何时决定使用一个版本而不是另一个版本?向量本身没有定义为常量,其中存储的元素也没有定义为常量。因此,给定两个函数:

A f(int i) const
    { return myVector[i]; }
A f(int i)
    { return myVector[i]; }
我的理解是,第一个调用运算符[]的常量版本并返回常量a。第二个调用非常量版本并返回非常量a

对我来说,f()的第一个版本似乎是要编写的“正确”版本,因为函数没有改变任何东西,但调用方可能会感到惊讶,因为它返回一个常量a。当然,如果我想要返回一个常量a,我应该将f()定义为:

这会告诉给来电者写信的人,他会收到一个常量


那么额外的常数是通过魔法出现的?如果我使用的是boost::ptr_向量而不是std::vector,那么额外的常量将应用于什么?数据?指针?两者?

函数声明末尾的
const
仅适用于非静态成员函数,这意味着
*此
是const限定的

struct A {
  void f(int i) const;
  void f(int i);
};

void g(const A& x, A& y) {
  x.f(); // calls const version
  y.f(); // calls non-const version
}

在STL容器中,这种重载用于确定返回的引用或迭代器是否可用于更改容器的元素。不能通过
const
限定容器更改元素

返回常量值实际上是毫无意义的——从常量左值构造新值是完全合法的,这就是为什么第一种形式是有效的。想想看——如果你想从某个地方复制,如果你不能在某个地方写信也没关系

如果您返回了一个引用,那么编译器将不允许您在const版本中返回a&值

在函数中:

A f(int i) const
    { return myVector[i]; }
您正在返回一个非常量a。由于您是按值返回的,因此运算符[](常量引用)返回的值将复制到一个新的a中。您正在“丢失”常量,但这并不重要,因为您有一个全新的对象。相反,如果您的类看起来像这样:

struct B {
  const A& f(int i) const;
  A& f(int i);

private:
  vector<A> myVector;
};

您的a将是常量引用。

这利用了函数重载规则中的一个棘手部分。首先,方法原型的右括号后面的cv限定符与参数上的cv限定符类似,但它们适用于隐式
参数。在一个假设的C++变体中,你必须声明<代码>这个< />代码,原型将是这样的:

reference operator[](this_type this, size_type n);
const_reference operator[](const this_type this, size_type n);
因此,如果调用方法的对象是
const
,则第二个重载更接近匹配,将被调用。如果不是,将调用第一个重载。因此,如果对
const
容器进行索引,则返回
const\u引用
;如果对非
const
容器进行索引,则返回
引用
。然后,
const\u引用
对象强制其指向的容器的只读性质


有时
const_reference
const reference
相同,有时则不同;对于更复杂的容器,
引用
是一个包含非平凡代码的类,对于只读类型,该代码必须不同。该标准始终使用
const_reference
,以便实现者在需要时可以自由地这样做。

您最好问一个关于“const”的一般性问题。甚至更好的是,在C++教科书中学习这些,并尝试示例程序,然后可能会问任何具体的问题。你在用哪本教科书?
const\u reference
几乎与
const reference
不同,除非
value\u type
已经是
const
。如果
reference
int&
const reference
也将是
int&
,而不是
const int&
const B b;
const A& a = b.f();
reference operator[](this_type this, size_type n);
const_reference operator[](const this_type this, size_type n);