'const'方法可以改变什么?
What can a 'const' method change?
C++方法允许const
限定符指示该方法未更改对象。但这意味着什么?例如。如果实例变量是指针,这是否意味着指针没有改变,或者它们指向的内存没有改变?
具体来说,这是一个最小的示例类
class myclass {
int * data;
myclass() {
data = new int[10];
}
~myclass() {
delete [] data;
}
void set(const int index) const {
data[index] = 1;
}
};
该方法set
正确符合const
条件吗?它不会data
改变成员变量,但它确实会改变数组的内容。
"常量"方法可以改变什么?
在不显式抛弃恒常性的情况下,const
成员函数可以更改:
-
mutable
数据成员,以及 - 类对任何数据具有非
const
访问权限,无论该数据是否可访问: - 通过作为指针或引用的成员变量,
- 通过作为函数参数传递的指针或引用,
- 通过函数返回的指针或引用,
- 直接在包含它的命名空间或类(对于静态成员(中。
这些限制也适用于数据成员和基础的操作(在 OO 意义上(。 更明确地说,在*this
的数据成员或基上运行的const
成员函数,当它们为class
/struct
/union
类型时,只能调用其const
成员函数(如果有(,并且只能写入其mutable
数据成员(如果有(。
(const
成员函数还可以更改任何非const
局部变量和按值参数,但我知道这不是您感兴趣的(。
const
数据成员可以调用其他const
成员函数,这些函数将具有这些相同的功能和限制。
例如,如果实例变量是指针,这是否意味着指针没有改变,或者它们指向的内存没有改变?
这意味着指针不能(容易/意外(更改。 这并不意味着指向的内存无法更改。
您偶然发现的是const
函数更改对象概念上拥有的指向或引用的数据的逻辑不正确。 正如您所发现的,编译器不会强制执行您可能希望或期望的const
正确性。 这有点危险,但意味着不需要显式删除对其他对象的指针/引用的恒定性,这些指针/引用可能会因const
函数的副作用而更改。 例如,日志记录对象。 (通常,此类对象在逻辑上不是由其const
函数对其进行操作的对象"拥有"的。 关键的一点是,编译器无法可靠地区分对象对指向数据的逻辑所有权类型,因此它必须以一种或另一种方式进行猜测,并允许程序员覆盖,或者不受const
-ness的保护。 C++放弃了保护。
有趣的是,我听说Walter Bright的D语言翻转了这个默认值,默认情况下在const
函数中const
指向的数据。 这对我来说似乎更安全,尽管很难想象一个人最终需要明确抛弃恒常性以允许想要的副作用的频率,以及这是否会令人满意地精确或令人讨厌的冗长。
最简洁地说,这意味着this
的类型const T *
在 const 成员函数中,其中 T
是你的类,而在非限定函数中它是T *
。
你的方法set
不会改变data
,所以它可以被定性为常量。换句话说,myclass::data
作为this->data
访问,并且类型为 int * const
。
这个问题有两个方面:
const
对编译器意味着什么?- 当编译器无法验证时,
const
如何应用?
问题1
第一个相当简单。 编译器验证是否未修改任何数据成员(除非它们被限定为 mutable
(。 它以递归方式验证这一点:对于任何用户定义的类型,它检查是否未调用任何非 const 方法。 对于内置类型,它会验证它们是否未分配。
指针的转换T*
T*const
(常量指针(,而不是const T*
(指向 const 的指针(。 这意味着编译器不会验证指向的对象是否未被修改。 显然,这就引出了问题2。
问题2
当编译器未验证时,const
如何应用? 它意味着它对您的应用程序意味着什么。 这通常被称为逻辑常量。 何时使用const
逻辑常性是有争议的。
const 应用于方法时意味着:
这意味着该方法不会更改对象的state
。
这意味着不能修改作为对象状态一部分的任何成员,也不能调用任何不是 const 的函数。
因为这与指针有关。这意味着指针(如果它是状态的一部分(不能更改。但是指针指向的对象是另一个对象的一部分,因此这意味着您可以对此对象调用非成本方法(因为它不是此对象状态的一部分(。
const
基本上可以防止更改函数中类实例成员的值。这对于更清晰的界面很有用,但在例如使用继承时会受到限制。它有时有点欺骗(或者实际上很多(,就像您发布的示例一样。
const
最适合Get
函数,其中很明显,调用方正在读取值并且无意更改对象状态。在这种情况下,您可能还需要限制继承的实现以遵守const
性,以避免在使用多态性时出现混淆和隐藏的错误。
例如
class A{
int i;
public:
virtual int GetI() {return i;};
}
class B : public A{
public:
int GetI() { i = i*2; return i;}; // undesirable
}
将 A 更改为:
virtual int GetI() const {return i;};
解决了问题。
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 警告处理为错误这里有什么问题
- 什么时候调用组成单元对象的析构函数
- #定义c-预处理器常量..我做错了什么
- 努力将整数转换为链表。不知道我在这里做错了什么
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 当矢量改变容量时,有什么方法可以更新指针/参考值
- 为什么左值不能改变自己。左值用户是什么意思?
- 有什么方法可以改变同步Windows API SendARP的行为吗?
- cocos2d-x每次我需要精灵或只是改变它的纹理时,制作精灵的最佳做法是什么
- 一个什么都不做的函数可以改变一个对象吗?
- 方法问题 - 什么会改变值,什么不会改变?什么是无效的?
- auto在c++ 11中的含义改变;请删除它这是什么意思
- 如何在java中做什么在c++中是改变一个被覆盖的方法的可见性
- c++地图值不改变运行时,我做错了什么
- 什么IDE可以成功地改变类型的所有变量从QSharedPointer到boost::shared_ptr
- 什么会导致一行代码在一个地方改变另一个不相关函数的行为
- 'const'方法可以改变什么?
- 在2D矢量的预定位置改变几个值的最简单方法是什么?
- 当我改变矢量时迭代器发生了什么