将const容器引用作为参数传递时,如何转义const_iterator陷阱

Cat*_*kul 2 c++ iterator stl const

我通常更喜欢constness,但最近遇到了一个与const迭代器的难题,震动了我的const态度让我很烦恼:

MyList::const_iterator find( const MyList & list, int identifier )
{
    // do some stuff to find identifier
    return retConstItor; // has to be const_iterator because list is const
}
Run Code Online (Sandbox Code Playgroud)

我想在这里表达,当然,这个想法是,在列表传递不能/ willnot改变,但一旦我做出的排行榜引用常量然后我必须使用"常量性的,然后阻止我与做任何事情对矫正结果(这是有道理的).

那么,解决方案是放弃制作传入的容器引用const,还是我错过了另一种可能性?

这一直是我对const的秘密保留:即使你正确使用它,它也可能产生在没有好/干净解决方案的情况下不应该出现的问题,尽管我认识到这更常见于const和迭代器的概念.

编辑:我非常清楚为什么你不能也不应该为const容器返回一个非const迭代器.我的问题是,虽然我要为我的容器中,按引用传递在编译时检查,我还是想找到一种方法,传回的东西的位置,并用它来修改列表的非const版本.正如其中一个答案中所提到的,可以通过"提前"提取这种位置概念,但是凌乱/低效.

rme*_*dor 10

如果我理解你说的正确,你试图用来const向调用者表明你的函数不会修改集合,但你希望调用者(可能没有const引用该集合)能够使用返回的迭代器修改集合.如果是这样,我认为没有一个干净的解决方案,除非容器提供了一个机制,用于将一个const交互器转换为非const一个(我不知道这样做的容器).你最好的选择可能是你的功能不const参考.您也可能有2个函数重载,const一个非一个const,因此对于只有一个const引用的调用者,它们仍然可以使用您的函数.


Joh*_*McG 6

这不是陷阱; 这是一个功能.(:-)

通常,您不能从const方法向数据返回非const"句柄".例如,以下代码是非法的.

class Foo
   {
      public:
         int& getX() const {return x;}
      private:
         int x;
   };
Run Code Online (Sandbox Code Playgroud)

如果它是合法的,那么你可以做这样的事情....

   int main()
   {
      const Foo f;
      f.getX() = 3; // changed value of const object
   }
Run Code Online (Sandbox Code Playgroud)

STL的设计者遵循这个约定,使用了const-iterators.


在你的情况下,const会给你带来的是能够在const集合上调用它.在这种情况下,您不希望返回的迭代器可以修改.但是如果集合是非常量的,你确实希望它可以修改.所以,您可能需要两个接口:

MyList::const_iterator find( const MyList & list, int identifier )
{
    // do some stuff to find identifier
    return retConstItor; // has to be const_iterator because list is const
}

MyList::iterator find( MyList & list, int identifier )
{
    // do some stuff to find identifier
    return retItor; 
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用一个模板功能完成所有操作

template<typename T>    
T find(T start, T end, int identifier);
Run Code Online (Sandbox Code Playgroud)

然后,如果输入迭代器是非const,则它将返回非const迭代器,如果它们是const,则返回const_iterator.

  • Catskul,如果函数将返回允许其他人修改列表的内容,那么该函数还需要权限来修改列表.该函数无法授予它没有的权限.您只需要接受该函数*允许*来修改列表,即使它没有行使该权限. (4认同)