c语言const:用好c++的const



const是c当中很有特色个语言功能它限制了对数据操作还限制了类成员行为而且是对c引用类型参数和返回值这个功能有益补充c员应该时时有意识地正确使用const关键字const对于变量来说个要求而对于来说个承诺对它所操作变量承诺由于const使用场合和使用对象很多要正确地使用它还是需要用番心思

const在些地方使用:
首先它可以修饰个变量此时这个const是这个变量个要求---它不可以被修改所以这个变量必须在时候被赋值化的后就不能赋值了个只读变量见本文末尾例子(2)这意味着它不可以以任何方式被赋值包括不能做赋值表达式左值同时不可以把它传递给那些没有承诺不更改它

那么如何做这个承诺呢看第 5段如果类型变量i是const那么它地址&i也是const从(3)中可以看出&i只能赋值给const指针变量p而不可以赋值给q我们可以通过赋值给*q而更改它所指向变量i. 从这里我们可以看到上述声明表示我们不可以通过p修改它所指向变量也就是说*p也是个常量了所以 *p = 5 这样表达式是(4)要注意 p作为个变量它自身是可以修改(6)p声明当中const要求不可以通过p更改它所指向是p对它所指向变量承诺当它所指向变量不需要这样承诺时p自然仍然可以指向那个变量(6)但是(7)仍然是p有承诺不可以改变它所指向变量另外如果我们想要求p指针变量自身也不可以修改那我们应该如(9)中所做并且注意此时r必须在化时候赋值否则它就不可能再被赋值了(10)而从(11)中我们可以看出指针变量k要求它自身是只读但是没有承诺不可以通过它来修改它所指向变量因而不可以把&i赋值给它

个对象例子被const修饰后它自身状态在化的后就不可以修改了这时候不仅上面约束必须成立而且我们不可以成员成员可能会修改它状态除非那个成员承诺不会修改this对象状态而承诺方式至少是在签名末尾加上"const"如(12)所示而如果这个要返回个非mutable数据成员引用那么返回类型必须加上const表示那个返回引用不可以被用于修改对象状态这样这个成员才完整地承诺了它不会被用于修改对象状态(13)否则就不可以说它是个常量成员(14)事实上如果定要返回数据成员引用(比如拷贝构造代价很大时)那么强烈建议返回const引用以便禁止修改这个数据成员否则将严重违反类封装性这种违反可能带来暂时编码方便性但是长期来看定会吃苦头

注意在(12)中虽然返回了数据成员message_但是我们返回是它个copy而不是那个对象自身所以get_message不可能被用于修改message_数据成员而(12.1)错就错在它返回了message_引用

那么什么是个对象状态呢默认是这个对象所有数据成员但是在有些情景下个对象某些成员变量可能对于它状态没有决定作用这完全决定于类设计者如果类Foo中有这样成员变量我们需要把它声明为mutable表示即使个Foo例子是常量我们也可以修改这个成员同理类 Foo那些承诺不修改对象状态也可以修改这个成员变量(12)类当中也可以有const数据成员它也像独立const变量完全不可以以任何方式修改它所以它必须在类构造化列表中被在构造体中化是不可以(15)

那么个独立或者类成员如何承诺不会修改传入变量自身呢?对于诸如(16)这样它们不会面临这个问题所有参数都是在传值在(17)例子中实际参数m, n传入add后它们值分别被赋值给其形参a和b的后两个实际参数m, n就和add无关了自然add不会修改到m和n真正需要面对这个问题是那些传递引用这里和下文引用是广义引用包括& 修饰引用类型变量以及通过传递指针值来“引用”到实际参数本身情形如例子(18). 当参数中有某个参数是在传递引用那么如果这个确实不需要修改那个实际参数本身那么定要把那个参数声明为const这样不仅可以传入可读可写变量作为那个实参而且可以传入个const变量我们已经承诺了不会修改那个实际参数本身值(19)参数中传递引用常常是很有效---如果对象拷贝构造代价很大或者要操纵实际参数自身---但是定要在可能时候声明引用为constconst在类中还有个用处---用于定义静态常量数据成员如例子(20)

在设计类时候必须考虑清楚哪些数据成员应该是const化后就不可以再修改;哪些数据成员是mutable对对象状态定义没有影响;哪些成员不会修改对象状态应该声明为常量不会修改对象状态;那些不会修改引用参数可以是const在应该和可以使用const 地方定使用它

const效果可能被些语言功能所抵消:1. const_cast<> 2. C风格强制类型转换在设计良好代码中我们要非常小心地使用这种抵消const功能语言功能特别是第2种应该被禁用例如使用者看到引用参数const属性会放心地把自己常量数据传入却想不到这个承诺是假这样bug非常难调试再比如个const返回了个const数据成员引用但是这个者却使用1或者2思路方法抵消了const作用那么这个对象状态改变很难追踪这样代码是非常危险代码应该坚决地避免使用在使用某些旧c语言代码时候我们可能不得不做 第2类强制转换这是员应该予以足够特殊标注和注释



在最新C语言标准(c99)中const也被引入了可以修饰参数和返回值以及变量使用思路方法和上面相同C标准库也同步做了更新所以在C语言中也是要在可以使用const地方定使用它原因也同上

(1) const i = 3;
(2) i = 5; ×
(3) const *p = &i; OK
*q = &i; ×
(4) *p = 5; ×
(5) j = 6; OK
(6) p = &j; Ok
(7) *p = 5; ×
(8) j = 5; OK
(9) const *const r = &i; OK
(10) r = &j; ×
(11) *const k = &i; ×

Foo {
message_;
const my_name_;
mutable junk_;
const size_t max_num_; (20)
public:
get_message const (12)
{
junk_ = 1; // OK
message_;
}

& get_message const; × (12.1)

const & get_message_ref const (13)
{
message_;
}

& get_message_ref (14)
{
message_;
}

Foo : my_name("david"){} (15)

}; // Foo

add( a, b); (16)

m = 6, n = 7; (17)
add(m, n); (17)

void negate(& a); (18)
void swap( *a, *b); (18)
size_t strlen(const char *); (19)
Tags:  constcast constchar const c语言const

延伸阅读

最新评论

发表评论