C++: Const Pointer
在 2010-09-26 原作基础上修改。日期改到 2015-03-26 使本文进入 C++ 文章群落,方便查阅。
1. pointer to const
首先确定一点:int const i; 与 const int i; 是一样的,都是定义一个 read-only 的 int i。
所以 int const *p; 与 const int *p; 也是一样的,都是定义一个 read-only 的 int *p。我们称这样的 p 为 pointer to const
这里有几点需要注意:
#include <stdio.h>
int main() {
int i1 = 30;
int i2 = 40;
const int *p = &i1;
p = &i2; // OK
i2 = 80;
printf("%d\n", *p); // output: 80
*p = 100; // ERROR. assignment of read-only location '*p'
}
*pread-only,并不是pread-only,所以p的值是可以改的(p = &i2;)&i1只是一个int *,所以把一个int *赋值给const int *是可以的(const int *p = &i1;)p = &i2;之后,对&i2这块地址的访问就有两种方式,一是非const的i2,二是const的*p,所以可以有i2 = 80;,而不能有*p = 100;
2. const pointer
int* const p; 是定义了一个 read-only 的 p,所以假如有 int* const p = &i1; 之后,就不能再有 p = &i2;了。但是 *p 的值是可以随便改的。我们称这样的 p 为 const pointer
3. const pointer to const
const int* const p; 就是说 p 和 *p 都是 read-only,结合 1 和 2 即可得它的特性。
4. 大实验
class T { };
int main() {
T t1, t2;
const T ct;
T* pt = &t1; // pt: pointer to T
const T* pct = &ct; // pct: pointer to const T
T* const cpt = &t2; // cpt: const pointer to T
pt = pct; // ERROR. invalid conversion from 'const T*' to 'T*'
pt = cpt; // OK
pct = pt; // OK
pct = cpt; // OK
// 因为是 const 所以无法二次赋值
cpt = pt; // ERROR. assignment of read-only variable 'cpt'
cpt = pct; // ERROR. assignment of read-only variable 'cpt'
}
class T { };
int main() {
T t;
const T ct;
T* pt = &t; // pt: pointer to T
const T* pct = &ct; // pct: pointer to const T
// cpt: const pointer to T
T* const cpt = pt; // OK
T* const cpt = pct; // ERROR. invalid conversion from 'const T*' to 'T*'
}
class T { };
void foo(T* pt) { /* do nothing */ }
void bar(const T* pct) { /* do nothing */ }
void baz(T* const cpt) { /* do nothing */ }
int main() {
T t1, t2;
const T ct;
T* pt = &t1; // pt: pointer to T
const T* pct = &ct; // pct: pointer to const T
T* const cpt = &t2; // cpt: const pointer to T
foo(pct); // ERROR. invalid conversion from 'const T*' to 'T*'
foo(cpt); // OK
bar(pt); // OK
bar(cpt); // OK
baz(pt); // OK
baz(pct); // ERROR. invalid conversion from 'const T*' to 'T*'
}
- 不能把
const T*赋值给一个T*- 反过来把
T*赋值给一个const T*是可以的 - 这一点和 C++: Const Reference 是相反的
- 反过来把
- 不能把
const T*实参传给一个T*形参- 反过来把
T*实参传给一个const T*形参是可以的 - 这一点和 C++: Const Reference 是类似的
- 反过来把
T* const除了const特性外,与T*性质是一样的(同上述 4 条)
class T {
public:
int i;
void modify();
T(int i);
};
T::T(int i) {
this->i = i;
}
void T::modify() {
i++;
}
int main() {
T t(1);
const T ct(3);
const T* pct1 = &ct;
const T* pct2 = &t;
t.modify(); // OK
ct.modify(); // ERROR. passing 'const T' as 'this' argument of 'void T::modify()' discards qualifiers
pct1->modify(); // ERROR. passing 'const T' as 'this' argument of 'void T::modify()' discards qualifiers
pct2->modify(); // ERROR. passing 'const T' as 'this' argument of 'void T::modify()' discards qualifiers
}
const T本身的值不能改- 即使你是把一个
T*(&t)赋给一个const T*(pct2),你也不能通过这个const T*去修改它的值,虽然你可以用T*直接去修改(t.modify();)- 由此看来,
const T*其实是一种契约精神!(说不能改就不能改) - 这一点和 C++: Const Reference 是相同的
- 由此看来,
5. 特殊情况
5.1 Force assignment with casting
前面有讲:不能把 const T* argument 传给一个 T* parameter
However, you can always use a cast to force such an assignment, but this is bad programming practice because you are then breaking the constness of the object, along with any safety promised by the const.
//: C08:PointerAssignment.cpp
const int e = 2;
int* w = (int*)&e; // Legal but bad practice
int main() {}
5.2 Character array literals
“不能把 const T* 赋值给一个 T*” 还有一个例外就是 char* cp = "howdy";:
- With
char* cp = "howdy";, a character array literal ("howdy"in this case) is created by the compiler as a constant character array, and the result of the quoted character array is its starting address in memory. - However, if you try to change the values in a character array literal, the behavior is undefined, although it will probably work on many machines.
- If you want to be able to modify the string, put it in an array:
char cp[] = "howdy";(这和上式有个毛的区别!)
留下评论