C/C++:混肴点分析

本文详细介绍了C++中的字面常量(包括整数、浮点数和字符),符号常量(使用#define和const定义)以及临时变量(如传值返回、类型转换和对象列表初始化)。着重讨论了C++中const关键字的实现原理和与宏定义的区别。
摘要由CSDN通过智能技术生成

C++中的常量介绍

字面常量

字面常量是指直接出现在代码中的常量值。例如,整数常量10、浮点数常量3.14、字符常量'A'等都属于字面常量。字面常量的值在编译时就已经确定,并且不能被修改。

字面常量存在类型,也有地址

注意字符常量和只包含一个字符的字符串在 C/C++ 中有一些区别:

1.表示方式:字符常量使用单引号括起来,例如 'A',而只包含一个字符的字符串使用双引号括起来,例如 "A"。

2.类型:字符常量的类型是 char

3.存储方式:字符常量在内存中占用一个字节的空间,而只包含一个字符的字符串会分配n+1的空间(n个用于存储字符,一个用于存储字符串结束符 \0)。

4.使用上的差异:字符常量可以直接赋值给一个 char 变量,例如 char ch = 'A';。而字符串不能直接赋值给 char 变量,需要使用字符指针或字符数组来处理,例如 const char* str = "ABC";指针需要加const。

5.操作上的差异:对字符常量进行操作时,可以直接使用字符之间的运算符,例如 'A' + 1;而对只包含一个字符的字符串进行操作时,需要使用字符串相关的函数或操作方法,例如 strlen()、strcpy() 等。

符号常量

符号常量是通过标识符来表示的常量值,在程序中使用时要先进行定义。使用符号常量的好处是可以给常量起一个具有描述性的名字,方便理解和维护代码。在C++中,我们通常使用const关键字来定义符号常量。

在C++中,符号常量的定义语法有两种方式:使用#define预处理指令和使用const关键字。

1.使用#define预处理指令定义常量:

#define 常量名 值

例子:

#define PI 3.14159

#define MAX_VALUE 100

用#define定义的常量是在编译前进行文本替换,没有类型限制,可以用于定义任何类型的常量

2.使用const关键字定义常量:

const 类型 常量名 = 值;

例子:

const int MAX_VALUE = 100;

const double PI = 3.14159;

使用const定义的常量有类型限制,可以用于定义任何类型的常量,也可以用于定义对象常量

C++的const分析

1:C++和C的const实现原理对比

C语言中的const修饰的变量实际上还是一个变量,只是一个只读变量,是可以通过指针来改变,改变方法就是对这个const变量取地址,然后用指针指向它,去修改这个指针指向的内容,所以说C语言中const修饰的并不是真正意义上的常量,而是一个只读变量。但是有一种情况例外,就是C语言用const修饰的全局变量,编译器把它放在只读存储区里面。

 C++里面的const修饰的变量,编译器对它的处理,是把这个放在符号表里面,符号表就是一个二维表,里面有符号和对应的值。假设采用与C语言类似的方法取地址,然后改变指针指向的内容的方法,const变量的内存还位于栈区或者静态存储区,原先空间的值依旧会改变,但符号表里的值没变,打印结果也不会变。所以C++里面的const修饰的的确是常量,而不是只读变量,C++里面对const常量使用了extern,也会分配存储空间。

const字符常量有空间,有地址

2:const与宏定义之间的区别

宏定义发生在预处理阶段,不会检查作用域和类型。这就是本质的区别。

void f()

{

    #define a 3

    const int b = 4;

}

void g()

{

    printf("a = %d\n", a);

    //printf("b = %d\n", b);

}

临时变量

临时变量是一种只在调用期间有效,且具有常性的变量,是字面常量或者符号常量。

临时变量是如何产生的?

1.传值返回

在main函数中我们调用add函数,add函数将sum的值返回,然后将sum的值赋值给re,可是当add函数调用一结束,sum作为add中的局部变量就会立即消亡,那么这个时候是如何将sum赋值给re的呢?

实际上这个时候临时变量就产生了关键的作用,编译器会创建一个临时变量,将sum的值拷贝给这个临时变量,返回的实际上是这个临时变量的值,函数调用结束将这个临时变量的值赋值给re。

2.强制类型转换/隐式类型转换

强制类型转换一定会产生临时变量,因为编译器并不会对原变量进行强制类型转换,而是将原变量的值强制类型转换为所转类型的值,然后将强制类型转换后的值赋值给相应类型的临时变量,不会改变原变量的类型。

3.const引用

const int& b = 2;  // const int temp =2, const int& b=temp 

cout << &b << endl; //0000009086CFF524

这里生成一个临时变量temp,对temp进行引用

4.变量列表初始化

定义一个变量并初始化
int units_sold=0;//直接赋值
int units_sold(0);//先调用构造,构造一个值为0的名为units_sold变量
int units_sold={0};  //列表初始化
int units_sold{0};    //列表初始化

生成一个临时变量,然后列表用数据初始化临时变量,最后赋值

5.变量列表引用

const int& b = { 1 };
const int& a{ 1 };

生成一个临时变量,然后列表用数据初始化临时变量,最后引用

临时对象

1.对象列表引用

class A
{
public:
	A(int a1, int a2)
		:_a1(a1)
		, _a2(a2)
	{}

private:
	int _a1;
	int _a2;
};

int main()
{
	// C++11
	const A& aa2 = { 1, 2 };
    //const A& aa2{ 1, 2 };

	return 0;
}

这里生成一个初始化为{1,2}的临时对象const A temp,给aa2引用,可以省略等于

2.对象列表初始化

class A
{
public:
	A(int a1, int a2)
		:_a1(a1)
		, _a2(a2)
	{}

private:
	int _a1;
	int _a2;
};

int main()
{
	// C++11
	A aa1 = { 1, 2 };
    //A aa1{1,2};

	return 0;
}

这里生成一个初始化为{1,2}的临时对象,将临时对象拷贝构造给对象aa1,可以省略等于

3.对象返回

class A
{
public:
	

private:
	int _a;
};
A f1()
{
	A aa;
    return aa;
}
int main()
{
	A bb = f1();
	return 0;
}

这里返回对象 aa,实际上是先生成一个临时对象,将对象aa拷贝构造给临时对象,然后返回临时对象

  • 22
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你好,赵志伟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值