stl容器中的const和非const

时间:2010-12-17 19:13:47

标签: c++ boost stl

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

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);}

编译器何时决定使用一个版本而不是另一个版本?向量本身未定义为const,也不存储在其中的元素。所以有两个功能:

A f(int i) const
    { return myVector[i]; }
A f(int i)
    { return myVector[i]; }

我的理解是第一个会调用operator []的const版本并返回一个const A.第二个调用非const版本并返回一个非const A?

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

const A f(int i) const    //Note the extra const at the start
    { return myVector[i]; }

这会告诉谁在编写调用者以期望const回来。

所以额外的const出现了吗?如果我使用boost :: ptr_vector而不是std :: vector,那么额外的const应用于什么?数据?指针?既?

4 个答案:

答案 0 :(得分:7)

这利用了函数重载规则的棘手部分。首先,在方法原型的紧密括号之后的cv限定符就像参数上的cv-qualifiers一样,但它们适用于隐式this参数。在假设的C ++变体中,你必须声明this,原型就是这样:

reference operator[](this_type this, size_type n);
const_reference operator[](const this_type this, size_type n);

因此,如果您在上调用方法的对象是const,则第二个重载是更接近的匹配并将被调用。如果不是,则会调用第一个重载。因此,如果索引const_reference容器,则会返回const,如果索引非reference容器,则会返回const。然后const_reference对象强制执行它所指向的容器的只读性质。

有时const_referenceconst reference相同,有时则不是reference。对于更复杂的容器,const_reference是一个具有重要代码的类,并且该代码必须与只读变量不同。该标准始终使用{{1}},以便实现者可以在需要时自由地执行此操作。

答案 1 :(得分:1)

函数声明末尾的const仅适用于非静态成员函数,意味着*this是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限定容器更改元素。

答案 2 :(得分:1)

在功能中:

A f(int i) const
    { return myVector[i]; }

你正在返回一个非const A.因为你按值返回,所以operator []返回的值(一个const引用)被复制到一个新的A.你正在“丢失”const,但它没有'因为你有一个全新的对象。相反,如果你的班级是这样的:

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

private:
  vector<A> myVector;
};

并使用const B调用f():

const B b;
const A& a = b.f();

你的a将是一个const引用。

答案 3 :(得分:0)

返回const rvalue实际上是没有意义的 - 从const值开始构造一个新值是完全合法的,这就是第一种形式有效的原​​因。想一想 - 如果你想从某个地方复制,如果你不能在某处写信那就没关系。

如果您返回了引用,那么编译器将不允许您返回A&amp;在const版本中。