const用法总结

C和C++中const的区别

C中的const

C语言中的const修饰的是只读变量,本质还是变量,有自己的存储空间。const的含义是不能通过被修饰的变量名来改变这块存储空间的值,并不是说这块存储空间的值是不能改变的,但在如下示例中:

#include <iostream>
uaing namespace std;
int main()
{
    const int a = 10;
    int *p = (int *)&a;
    *p = 20;
    printf("a = %d\n", a);
    return 0;
}

可以通过一个指针指向a所代表的内存空间,进而间接改变这块空间的值。另外,const修饰的仍然是变量,不可以用const修饰的变量作为数组长度去定义数组,如:

const int a = 10;
int arr[a];

这在某些编译器可能无法编译通过。

C++中的const

在C++中,const修饰的是真正的常量,而不是C中的只读变量。const常量会被编译器放入符号表中,符号表中存储的是一系列键值对,所以一般情况下,编译器不会为const常量分配内存空间。但是,当我们要对一个const常量进行取地址或者extern操作时编译器就会为该常量分配存储空间。并且,当我们使用const常量时,值是从符号表中或取得,而不是使用分配的存储空间的值。例如:

#include <iostream>
using namespace std;
int main()
{
    const int a = 10;
	int *p = (int *)&a;
	*p = 20;

	printf("&a = %p, p = %p\n", &a, p);
	print("a = %d, *p = %d\n", a, *p);

    return 0;
}

运行发现,&a与p输出的地址相同,但第二行的a和*p输出的值不一样,a输出还是10,*p输出20。a有自己的存储空间,但是在使用a的时候,并不是使用这个存储空间的值,而是从符号表中取出的值。

const与define

const与define的相同之处

C++中的const和define都可以用来定义常量,可以作为数组长度定义数组:

#define AAA	10
const int a = 20;
int arr1[AAA];
int arr2[a];

const与define的不同之处

const常量是由编译器处理的,提供类型检查和作用域检查,而define是有预处理器处理的,只是简单的文本替换。

const与指针结合

const int *p;

p所指向的空间的值不可修改,但可以更改p的值,指向其它地址空间。

int const *p;

同上

int* const p;

p所指向的空间可以的值可以修改,但p值不能修改,也就是不能指向其它空间。

注:在判断此类问题时,可以将数据类型int遮住,看const右边最靠近谁,如:

const *p;
const *p;
* const p;

const右边靠近星号(*),则指向空间的值不可修改,但p值可以修改
const右边靠近变量名,则p值不可修改,但所指向空间的值可以修改。

const与类

用在成员方法中修饰this指针

在类的成员方法中,会隐式添加一个this指针(ClassName* const this),作为函数的第一个参数(隐藏),这个指针指向当前操作的对象,this是一个常指针,函数内部可以通过this指针获取、修改成员变量的值,但很多情况下,我们只是获取成员变量的值,并不希望被修改成员变量,就需要对this指针做进一步的限制,将其改成const ClassName* const this,const成员函数也成为常成员函数:

DataType func(DataType name) const{}

const修饰成员变量

如果类中有const修饰的成员变量,初始化const成员变量的唯一方法是通过构造函数的参数初始化表,如:

class A
{
public:
	A(int a, int b, int c):m_a(a), m_b(b)
	{
		m_c = c;
	}

private:
	int m_a;
	const int m_b;
	int m_c;
}

const与引用结合

引用在作为函数参数传递事务,形参与实参代表的是同一块内存,若不希望函数内部修改实参,在定义的时候最好定义成常引用。定义的方式:

const Type &name = var;

常引用的初始化方式有两种。

  • 用一个普通变量去初始化常引用:
int a;
const int &b = a;

b是a的常引用,a和b代表的是同一块空间,但是不能通过b来修改a的值。

  • 使用常量去初始化常引用
const int &a = 10;

常量10没有地址空间,当用常量对const引用初始化时,编译器会在内存中开辟一块空间,并用这个常量的值对新开辟的空间进行初始化,燃火将a作为这块空间的别名。

注:常量可以初始化常引用,但是不能初始化普通引用,如下语句是不合法的:

 int &a = 10;

因此,如下写法也会报错:

int add(int &a, int &d);
add(10, 20);

const形参与函数重载

如果const修饰的是指针变量,可以通过判断它指向的是常量对象还是非常量对象,可以实现函数的重载,例如下面两个函数:

void add(int *a, int *b)
void add(const int *a, const int *b);

编译器可以通过判断实参是否常量来判断应该调用哪个函数。完整示例代码:

#include <iostream>
using namespace std;

void add(int *a, int *b)
{
	cout << "(int *num)sum = " << *a + *b << endl;
}

void add(const int *a, const int *b)
{
	cout << "(const int *num)sum = " << *a + *b << endl;
}

void add(int &a, int &b)
{
	cout << "(int &num)sum = " << a + b << endl;
}

void add(const int &a, const int &b)
{
	cout << "(const int &num)sum = " << a + b << endl;
}

int main()
{
	const int a = 1;
	int b = 2;
	add(&a, &a);
	add(&b, &b);
	add(a, a);
	add(b, b);
	return 0;
}

运行结果:

(const int *num)sum = 2
(int *num)sum = 4
(const int &num)sum = 2
(int &num)sum = 4

当传入的实参是const常量对象时,编译器会优先调用const常量形参函数,当实参是非const常量对象时,编译器会优先调用非const常量形参函数。如果将两个带有const形参的函数去掉,也可以编译运行。

const作为函数返回值

const int func();

  • 待整理

const int & func();

  • 待整理
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值