在 2010-09-26 原作基础上修改。日期改到 2015-03-26 使本文进入 C++ 文章群落,方便查阅。
1. pointer to const
首先确定一点,int const i; 与 const int i; 是一样的,都是定义一个只读的 int i。
所以 int const *p; 与 const int *p; 也是一样的,都是定义一个只读的 int *p。我们称这样的 p 为 pointer to const
const int *p;
: Starting from the identifier, we read “p is a pointer, which points to a const int.”int const *p;
: p is an ordinary pointer to an int that is const
但是,不管是 int const *p; 还是 const int *p;,这里有几点需要注意:
#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'
}
- 首先是 *p 只读,并不是 p 只读,所以 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; 是定义了一个只读的 p,所以假如有 int * const p = &i1; 之后,就不能再有 p = &i2;了。但是 *p 的值是可以随便改的。我们称这样的 p 为 const pointer
int * const p = &i1;
: p is a pointer, which is const, that points to an int
3. const pointer to const
const int * const p; 就是说 p 和 *p 都是只读的,结合 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 是相同的
- 由此看来,
blog comments powered by Disqus