C++常量、#define、const和constexpr

C++常量、#define、const和constexpr

常量

常量是固定值,在程序执行期间不会改变,可以是任何的基本数据类型,可分为整型数字、浮点数字、字符、字符串和布尔值,常量的值在定义后不能进行修改;

可以使用枚举、#define、const和constexpr等方法定义常量.

#define

#define是预处理阶段进行处理,是一种宏定义,所以定义常量的宏是没有类型的,是在编译前即预编译阶段进行字符替换,并且由于是在预处理阶段替换所以不会有类型安全检查,系统也不会为它分配内存,存储在程序的代码段空间,实际就是给出了立即数,在运行过程中,常量在内存中会有若干个拷贝;

1
2
#define Pi 3.1415926
S = Pi * r * r //这里Pi会替换成3.1415926

如果只想常量宏只在某段代码起作用,则使用#undef这个常量宏,如果再用到了这个常量宏,编译器就会报错

1
2
3
4
5
#define Pi 3.1415926
S = Pi * r * r; //这里Pi会替换成3.1415926
#undef

S = Pi + 1; //编译器报错

const

const是一种Runtime,const常量会在内存中分配,可以是堆中也可以是栈中。以后在定义的常量调用时,只是使用对应的内存地址,不再开辟新的空间,在内存中只有一个拷贝,因此const相比#define,可以避免反复分配内存,节省空间

1
2
const doulbe Pi=3.14159;
S = Pi * r * r;

const修饰指针

const位于*的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量

1
2
3
4
int test = 1;
const int* test_ptr = &test;//禁止修改test_ptr指向的值, 可以修改test_ptr的值
int test2 = 2;
test_ptr = &test2;//指向另一个变量

const位于*的右侧,const就是修饰指针本身,即指针本身是常量

1
2
3
4
int test = 1;
int* const test_ptr = &test;

*test_ptr = 20; // 可以修改test_ptr指向的值, 禁止修改test_ptr的值

const修饰函数

在类中将成员函数修饰为const表明在该函数体内,不能修改对象的数据成员而且不能调用非const函数,由于非const函数可能修改数据成员,const成员函数是不能修改数据成员的,所以在const成员函数内只能调用const函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class A
{
private:
int i;
public:
void fun1(int n) //fun1函数需要设置i的值,所以不能声明为const
{
i = n;
}

int fun2() const //fun2函数返回i的值,不需要对i进行修改,则可以用const修饰。防止在函数体内对i进行修改。
{
return i;
}
};

const修饰函数参数

const修饰的函数参数是指针时,代表在函数体内不能修改该指针所指的内容,起到保护作用;const指针可以接收非const和const指针,而非const指针只能接收非const指针

1
void Test(const int param);

const修饰函数返回值

const来修饰返回的指针或引用,保护指针指向的内容或引用的内容不被修改,也常用于运算符重载。归根究底就是使得函数调用表达式不能作为左值

1
const int* Test();

const修饰成员变量

1
2
3
4
5
6
7
8
9
10
11
12
class Test
{
public:
void fun1()const;
private:
int i;
}

void Test:: fun1() const
{
//i++; i不能修改
}

constexpr

constexpr与const一样,它可以应用于变量,不同的是可以应用于函数和类构造函数,constexpr指示值或返回值是常量,并且在可能的情况下,在编译时计算

修饰变量

const和constexpr之间的主要区别在于,const的初始化可以在到运行时,而constexpr编译时必须初始化

1
2
3
4
5
6
constexpr float exp(float x, int n)
{
return n == 0 ? 1 :
n % 2 == 0 ? exp(x * x, n / 2) :
exp(x * x, (n - 1) / 2) * x;
}

修饰构造函数

constexpr还能用于修饰类的构造函数,即保证如果提供给该构造函数的参数都是constexpr,那么产生的对象中的所有成员都会是constexpr,该对象也就是constexpr对象了,可用于各种只能使用constexpr的场合。注意,constexpr构造函数必须有一个空的函数体,即所有成员变量的初始化都放到初始化列表中

1
2
3
4
5
6
7
8
9
10
11
12
struct Base
{
constexpr Base(int xx, int yy,int zz)
:x(xx),y(yy),z(zz){}
constexpr Base()
:Base(0,0,0){}
int x;
int y;
int z;
};

constexpr Base pt = {100,100,100};

转载自C/C++ 常量、#define、const和constexpr


C++常量、#define、const和constexpr
https://gstarmin.github.io/2023/03/06/Cpp中define、const和constexpr/
作者
Starmin
发布于
2023年3月6日
许可协议