const int a = 0; // 必须赋初始值,然后不能被重新赋值
file1.cpp
extern const int aext = 100;
file2.cpp
extern const int aext; // 使用的是file1.cpp中的aext变量
分为顶层const和底层const
const int *p; // 修饰的是指针指向的对象,表示指向的是常量对象。可以使用非常量变量取地址初始化,只是限制不能通过p来改变这个变量的值
int * const p = nullptr; // 修饰的是指针本身,表示常量指针。 常量对象必须被初始化
const int * const p = nullptr; // 必须被初始化,可以使用非常量对象取地址初始化
const int a = 32; // a为顶层
const int &r = a; // r为底层,用于声明引用的const都是底层
const int * const p = &a; // 指针既可以为顶层,也可以为底层
int b = a; // 正确,顶层属性忽略
int a = 0;
const int b = 0;
int &b = a;
const int &aa = a; // 非常量左值,相当于const int *p能指向一个非常量变量。
const int &bb = b; // 常量左值(普通引用不能引用常量值)
const int &cc = 0; // 右值(普通引用不行)
const int &dd = a + b; // 接收表达式(普通引用不行),可以理解为常引用的是一个a+b返回的临时变量。
int a = 23;
void print(const int aa) { };
print(a); // 非const变量可以传递给const属性形参
void print(int aa) { }; // 错误,和const版本重定义
void print( int * const p);
void print(int *p); // 错误,与顶层const版本重定义
void print(const int *p); // 单独的底层const版本, 指向的是常量对象,不能通过指针改指向变量的值。可以接收非常量参数
int a = 9;
void print(int *p);
void print(const int *p); // 底层const版本,不会重定义
void print(const int a);
void print(const int &a); // 引用是底层的,不会重定义
const int print(); // 值传递变量到外部,相当于拷贝一份内容到外界接收地址
const int a = print();
int a = print(); // 非常量也可以接收返回值,所以返回const意义不大
const int *printConst(); // 返回的常量对象
const int *a = printConst(); // 只能由const指针接收
const int &r = printR(); // 由const int &接收返回值。前提不能返回局部变量和数值常量如0。
class A {
public:
void print() const; // const成员不能访问非const成员函数,能只读访问非const变量
void print1(); // 非const成员能访问const成员函数和成员变量。
int a;
const int a;
}
Class ClassA {
public:
void printC() const;
void print();
const int ac = 9;
int a;
}
const ClassA cls;
cls.printC();
cls.print(); // 错误 不能访问非const函数
::std::cout << cls.ac << cls.a << ::std::endl; // 可以只读访问非const的变量
cls.a++; // 不能改变非const成员变量
const int arr[3] = { 1, 2, 3};
int ia = 3;
int ib = 4;
int ic = 3;
const int *arr[3] = { &ia, &ib, &ic };
常量引用数组: 没有这种语法,引用本身是个别名,不占内存(实质上和占指针大小内存),编译器不知道给引用数组分配多少内存。
constexpr int a = 33; // 常量表达式,全局变量
int b = 33; // 全局变量
const int *p; // 表示p是指向常量的指针
constexpr int *p = nullptr; // 表示常量指针,转移成了顶层指针,且在编译阶段要确定实际值。
constexpr const int *pp = &a; // constexpr修饰pp是常量指针,const表示指向整型常量,a必须在编译时有地址(static,全局)。
constexpr int *p = &b;
constexpr int getCount(int count) { return count * 3;};
int ia = 3;
::std::array<int, getCount(3)> arr; // 返回常量表达式
::std::array<int, getCount(ia)> arr; // 编译错误,返回的不是常量表达式
cosntexpr int print(int a) { return a > 4 ? a : 4; };
constexpr int print(double x = 3.3, int a = 3);
constexpr int printTt(int a)
{
if (a > 4) {
return a;
} else {
return 4;
}
}
constexpr void print(void);
constexpr在c++98,c++11,c++14的实现
备注:
Class ClassA {
public:
const static int a = 3; // 声明式
}
xxx.cpp
const int ClassA::a; // 定义式,声明式已经赋了初始值,定义式不用在赋值。
Class classA {
public:
void changeInnerValue() const;
mutable int aa;
}
void ClassA::changeInnerValue() const
{
aa = 22; // 如果aa不用mutable修饰,const函数是不能改变其值的
}