我一直以为在类方法的签名中使用const关键字意味着这个方法不会修改它所调用的对象的字段.
但是,当我们使用例如向量时,对于不是const的operator []有一个重载:
whateverT & vector<whateverT>::operator [] ( size_t pos )
无论您使用的引用方式如何,即使引用的项目被修改,它也不会对向量的字段进行任何修改.
另一个例子 :
template<class T> class Array { T * _items; T & operator [] ( size_t pos ) const { return _items[ pos ]; } }
我可以使用const关键字,因为_items的值不被修改(不管我们用什么指向它).对于编译器,这是正确的,但是如果我访问其中一个项目并对其进行修改,那么operator []将允许修改数组,即使它应该是const,也就是说不应该修改数组的“content” .
在这种情况下应该做什么?使用或不使用const关键字?
谢谢 :)
解决方法
“引用其他对象”可以代表至少两种不同的设计关系:
>它可以用于实现聚合,在这种情况下,裁判被认为是引荐来源的组成部分.在这种情况下,您通常应该强制执行访问完整对象的所有部分的常量:如果引用者不变,则裁判员也应被视为不变的.您有责任通过适当地对您的课堂界面进行限定来执行后者.
为了支持这个概念,你通常不会尝试修改引荐来源的const方法中的裁判(尽管它是正式可能的).另一种方法是:如果某些引用方法修改了裁判的内容,那么您不应该声明该方法const(即使是正式可能).此外,引用的const方法不应该返回非常数引用的裁判.
在这种情况下,外部世界甚至不应该知道聚合对象通过引用存储.这只是一个实现细节.对于外部世界,所有内容都应该看起来像聚合对象是引荐来源的直接成员.
这正是您在std :: vector的情况下观察到的.它被设计为确保整个向量的常数传播到向量元素的常数的方式.为了实现它实现两个版本的operator []
reference operator[]( size_type pos ); const_reference operator[]( size_type pos ) const;
>它可以用于实现并不意味着聚合的纯引用.在这种情况下,裁判被认为是一个完全独立的,不相关的对象.引荐人的惯例不应该传播给裁判.在这种情况下可以修改引荐来源的const方法中的裁判.从引用来自的const方法返回非常数引用到裁判是可以的.
这个设计的一个例子是标准的智能指针:指针指向指针,但是指针的常量并不意味着指针的一致性.例如,std :: shared_ptr只有一个版本的operator *
T& operator*() const;
这被声明为const,但仍返回一个非常量的引用对象.