const 是不变的意思,修饰内置类型变量、自定义对象、成员函数、返回值,函数参数。
# 修饰普通类型变量
变量的值不能被修改。
#include <iostream> | |
using namespace std; | |
int main() { | |
int a = 1; | |
cout << "a: " << a << endl; | |
a = 2; | |
cout << "a++: " << a << endl; | |
const int b = 2; | |
cout << "b: " << b << endl; | |
// b = 2; error: assignment of read-only variable ‘b’ | |
} |
输出:
a: 1
a++: 2
b: 2
如果把常量的地址赋给非常量指针,修改指针的值,常量的值也不会被改变。
#include <iostream> | |
using namespace std; | |
int main() { | |
const int b = 2; | |
cout << "b: " << b << endl; | |
// b = 2; error: assignment of read-only variable ‘b’ | |
int* a = (int*) &b; | |
cout << "a: " << *a << endl; | |
*a = 3; | |
cout << "a: " << *a << endl; | |
cout << "b: " << b << endl; | |
} |
输出:
b: 2
a: 2
a: 3
b: 2
加上 volatile 修饰符,常量的值就会被改变。
#include <iostream> | |
using namespace std; | |
int main() { | |
volatile const int b = 2; | |
cout << "b: " << b << endl; | |
// b = 2; error: assignment of read-only variable ‘b’ | |
int* a = (int*) &b; | |
cout << "a: " << *a << endl; | |
*a = 3; | |
cout << "a: " << *a << endl; | |
cout << "b: " << b << endl; | |
} |
输出:
b: 2
a: 2
a: 3
b: 3
# 修饰指针变量
分为三种情况:
- 修饰指针指向的内容,则内容为不可变量。
- 修饰指针,则指针为不可变量。
- 修饰指针和指针指向的内容,则指针和指针指向的内容都为不可变量。
#include <iostream> | |
using namespace std; | |
int main() { | |
int a = 1; | |
int b = 2; | |
const int* c = &a; | |
cout << "const int* c: " << *c <<endl; | |
// *c = 2; error: assignment of read-only location ‘* c’ | |
c = &b; | |
cout << "c = &b: " << *c << endl; | |
int* const d = &a; | |
cout << "int* const d: " << *d << endl; | |
*d = 3; | |
cout << "*d = 3: " << *d << endl; | |
// d = &b; error: assignment of read-only variable ‘d’ | |
const int* const e = &a; | |
// *e = 4; error: assignment of read-only location ‘*(const int*)e’ | |
// e = &b; error: assignment of read-only variable ‘e’ | |
} |
输出:
const int* c: 1
c = &b: 2
int* const d: 1
*d = 3: 3
# 修饰引用
修饰引用时,对应变量的值不可改变。
#include <iostream> | |
using namespace std; | |
int main() { | |
const int& b = 10; | |
// b = 20; error: Cannot assign to variable 'b' with const-qualified type 'const int &' | |
} |
# 修饰函数参数
修饰参数时,分为三种情况:
- 修饰值传递变量,一般这种情况不需要 const 修饰,因为函数会自动产生临时变量复制实参值,这种情况函数内不能修改参数值。
- 修饰指针参数,指针不能被修改,同指针变量。
- 自定义类型的参数传递,需要临时对象复制参数,对于临时对象的构造,需要调用构造函数,比较浪费时间,因此我们采取 const 外加引用传递的方法。
#include <iostream> | |
using namespace std; | |
class A { | |
public: | |
A() {} | |
A(int a):a(a) {} | |
int get_a() const { | |
return a; | |
} | |
void add_a() { | |
++a; | |
} | |
private: | |
int a; | |
}; | |
void func1(const int a) { | |
// ++a; error: increment of read-only parameter ‘a’ | |
cout << "const int a: " << a << endl; | |
} | |
void func2(const int* a) { | |
// ++*a; error: increment of read-only location ‘* a’ | |
cout << "const int* a: " << *a << endl; | |
int b = 2; | |
a = &b; | |
cout << "a = &b: " << *a << endl; | |
} | |
void func3(int* const a) { | |
cout << "int* const a: " << *a << endl; | |
++*a; | |
cout << "++*a: " << *a << endl; | |
int b = 2; | |
// a = &b; error: assignment of read-only parameter ‘a’ | |
} | |
void func4(const int* const a) { | |
cout << "const int* const a: " << *a << endl; | |
// ++*a; error: increment of read-only location ‘*(const int*)a’ | |
int b = 2; | |
// a = &b; error: assignment of read-only parameter ‘a’ | |
} | |
void func5(const A a) { | |
cout << "const A a: " << a.get_a() << endl; | |
// a.add_a(); error: passing ‘const A’ as ‘this’ argument of ‘void A::add_a()’ discards qualifiers [-fpermissive] | |
} | |
void func6(const A* a) { | |
cout << "const A* a: " << a -> get_a() << endl; | |
// a -> add_a(); error: passing ‘const A’ as ‘this’ argument of ‘void A::add_a()’ discards qualifiers [-fpermissive] | |
A bb(4); | |
a = &bb; | |
cout << "a = &b: " << a -> get_a() << endl; | |
} | |
void func7(A* const a) { | |
cout << "A* const a: " << a -> get_a() << endl; | |
// a.add_a(); error: request for member ‘add_a’ in ‘a’, which is of pointer type ‘A* const’ (maybe you meant to use ‘->’ ?) | |
A bb(4); | |
// a = &bb; error: assignment of read-only parameter ‘a’ | |
} | |
void func8(const A* const a) { | |
cout << "const A* const a: " << a -> get_a() << endl; | |
// a.add_a(); error: request for member ‘add_a’ in ‘a’, which is of pointer type ‘const A* const’ (maybe you meant to use ‘->’ ?) | |
A bb(4); | |
// a = &bb; error: assignment of read-only parameter ‘a’ | |
} | |
void func9(const A& a) { | |
cout << "const A& a: " << a.get_a() << endl; | |
// a.add_a(); error: passing ‘const A’ as ‘this’ argument of ‘void A::add_a()’ discards qualifiers [-fpermissive] | |
A bb(4); | |
// a = &bb; error: passing ‘const A’ as ‘this’ argument of ‘A& A::operator=(const A&)’ discards qualifiers [-fpermissive] | |
} | |
int main() { | |
int a = 1; | |
func1(a); | |
func2(&a); | |
func3(&a); | |
func4(&a); | |
A aa(3); | |
func5(aa); | |
func6(&aa); | |
func7(&aa); | |
func8(&aa); | |
func9(aa); | |
} |
输出:
const int a: 1
const int* a: 1
a = &b: 2
int* const a: 1
++*a: 2
const int* const a: 2
const A a: 3
const A* a: 3
a = &b: 4
A* const a: 3
const A* const a: 3
const A& a: 3
# 修饰函数返回值
- 如果函数返回值采用 “值传递方式”,由于函数会把返回值复制到外部临时的存储单元中,加 const 修饰没有任何价值。
- 如果给以 “指针传递” 方式的函数返回值加 const 修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加 const 修饰的同类型指针;
#include <iostream> | |
using namespace std; | |
class A { | |
public: | |
A() {} | |
A(int a):a(a) {} | |
int get_a() const { | |
return a; | |
} | |
void add_a() { | |
++a; | |
} | |
private: | |
int a; | |
}; | |
const int func1() { | |
return 1; | |
} | |
const A func2() { | |
return A(3); | |
} | |
const A func3() { | |
A a(6); | |
return a; | |
} | |
const A* func4() { | |
A a(8); | |
A* b = &a; | |
return b; | |
} | |
const A& func5() { | |
A a(9); | |
A& b = a; | |
return b; | |
} | |
int main() { | |
int a = func1(); | |
cout << "int: " << a << endl; | |
cout << "++a: " << ++a << endl; | |
const int b = func1(); | |
cout << "const int: " << b << endl; | |
// cout << "++b: " << ++b << endl; error: increment of read-only variable ‘b’ | |
A c = func2(); | |
cout << "A: " << c.get_a() << endl; | |
c.add_a(); | |
cout << "c.add_a(): " << c.get_a() << endl; | |
c = A(5); | |
cout << "c = A(5): " << c.get_a() << endl; | |
const A d = func2(); | |
cout << "const A: " << d.get_a() << endl; | |
// d.add_a(); error: passing ‘const A’ as ‘this’ argument of ‘void A::add_a()’ discards qualifiers [-fpermissive] | |
// d = A(5); error: passing ‘const A’ as ‘this’ argument of ‘A& A::operator=(const A&)’ discards qualifiers [-fpermissive] | |
A e = func3(); | |
cout << "A: " << e.get_a() << endl; | |
e.add_a(); | |
cout << "e.add_a(): " << e.get_a() << endl; | |
e = A(7); | |
cout << "e = A(7): " << e.get_a() << endl; | |
const A f = func3(); | |
cout << "const A: " << f.get_a() << endl; | |
// f.add_a(); error: passing ‘const A’ as ‘this’ argument of ‘void A::add_a()’ discards qualifiers [-fpermissive] | |
// f = A(7); error: passing ‘const A’ as ‘this’ argument of ‘A& A::operator=(const A&)’ discards qualifiers [-fpermissive] | |
// A g* = func4(); error: expected initializer before ‘*’ token | |
const A* h = func4(); | |
cout << "const A*: " << h -> get_a() << endl; | |
// h -> add_a(); error: passing ‘const A’ as ‘this’ argument of ‘void A::add_a()’ discards qualifiers [-fpermissive] | |
// A& i = func5(); error: invalid initialization of reference of type ‘A&’ from expression of type ‘const A’ | |
const A& j = func5(); | |
cout << "const A&: " << j.get_a() << endl; | |
// j.add_a(); error: passing ‘const A’ as ‘this’ argument of ‘void A::add_a()’ discards qualifiers [-fpermissive] | |
} |
输出:
int: 1
++a: 2
const int: 1
A: 3
c.add_a(): 4
c = A(5): 5
const A: 3
A: 6
e.add_a(): 7
e = A(7): 7
const A: 6
const A*: 8
const A&: 9
# 修饰类成员函数
在上面可以发现,const 类型的指针或引用可以调用 get_a () 方法,这是因为其后有 const 修饰,认为这个方法不会改变对象的值。
如果被 const 修饰的成员函数想要修改成员变量的值,可以使用 mutable 修饰成员变量,表示可变化的。
#include <iostream> | |
using namespace std; | |
class A { | |
public: | |
A() {} | |
A(int a, int b):a(a),b(b) {} | |
int get_a() const { | |
// ++a error: increment of member ‘A::a’ in read-only object | |
return a; | |
} | |
int get_b() const { | |
++b; | |
return b; | |
} | |
void add_a() { | |
++a; | |
} | |
private: | |
int a; | |
mutable int b; | |
}; | |
int main() { | |
A aa(1, 1); | |
cout << "aa.a=" << aa.get_a() << endl; | |
cout << "aa.b=" << aa.get_b() << endl; | |
} |
输出:
aa.a=1
aa.b=2