C++深度解析(2)—C/C++中的const分析
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了C++深度解析(2)—C/C++中的const分析,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含7071字,纯文字阅读大概需要11分钟。
内容图文
![C++深度解析(2)—C/C++中的const分析](/upload/InfoBanner/zyjiaocheng/756/5e0460028dcf4e3bade5626fc8394a65.jpg)
1.C语言中的const
1.1 const只读变量
- const修饰的变量是只读的,本质还是变量
- const修饰的局部变量在栈上分配空间
- const修饰的全局变量在全局数据区分配空间
- const只在编译期有用,在运行期无用
- const修饰的变量不是真的变量,它只是告诉编译器该变量不能出现在赋值符号的左边
1.2 const全局变量的分歧
- 在现代C语言编译器中,修改const全局变量将导致程序崩溃
- 标准C语言编译器不会将const修饰的全局变量存储于只读存储区中,而是存储于可修改的全局数据区,其值依然可以改变。
#include <stdio.h>
const int g_cc = 2;
int main()
{
const int cc = 1;
int* p = (int*)&cc;
printf("cc = %d\n", cc);
*p = 3;
printf("cc = %d\n", cc);
p = (int*)&g_cc;
printf("g_cc = %d\n", g_cc);
*p = 4;
printf("g_cc = %d\n", g_cc);
return 0;
}
- gcc、VS2017、BCC(标准C)编译结果:
1.3 const的本质
- C语言中的const使得变量具有只读属性
- 现代C编译器中的const将具有全局生命周期变量存储于只读存储区(所以gcc、vs2017都会出错)
- const不能定义真正意义上的常量
#include <stdio.h>
const int g_array[5] = {0};
void modify(int* p, int v)
{
*p = v;
}
int main()
{
int const i = 0;
const static int j = 0;
int const array[5] = {0};
modify((int*)&i, 1); // ok
modify((int*)&j, 2); // error
modify((int*)&array[0], 3); // ok
modify((int*)&g_array[0], 4); // error
printf("i = %d\n", i);
printf("j = %d\n", j);
printf("array[0] = %d\n", array[0]);
printf("g_array[0] = %d\n", g_array[0]);
return 0;
}
- gcc、BCC(标准C)编译结果:
1.6 const修饰函数参数和返回值
- const修饰函数参数表示在函数体内不希望改变参数的值
- const修饰函数返回值表示返回值不可改变,多用于返回指针的情形
- 小贴士:C语言中的字符串字面量存储于只读存储区,在程序中需要使用 const char* 指针。
#include <stdio.h>
const char* f(const int i)
{
// i = 5; //error: assignment of read-only parameter ‘i’
return "Test";
}
int main()
{
const char* pc = f(0);
printf("%s\n", pc);
// pc[6] = '_'; //test.c:16:11: error: assignment of read-only location ‘*(pc + 6u)’
printf("%s\n", pc);
return 0;
}
- 运行结果
1.7 小结
- const使得变量具有只读属性
- const不能定义真正意义上的常量
- const将具有全局生命期的变量存储于只读存储区
2 C++中的const
2.1 编程实验 test.cpp
#include <stdio.h>
int main()
{
const int c = 0;
int* p = (int*)&c;
printf("Begin...\n");
*p = 5;
printf("c = %d\n", c);
printf("*p = %d\n", *p);
printf("End...\n");
return 0;
}
- vs2017运行结果:
2.2 C++中的const
- C++在C的基础上对const进行了进化处
- 当碰见const声明时在符号表中放入常量
- 编译过程中若发现使用常量则直接以符号表中的值替换
- 编译过程中若发现下述情况则给对应的常量分配空间
- 1. 对const常量使用了extern
- 2. 对const常量使用&操作符
- 注意:C++编译器虽然可能为const常量分配空间,但不会使用其存储空间的值。
- 当遇到&c时,为其分配空间,分配空间只是为了兼容C语言
- C语言中的const变量:C语言中const变量是只读变量,会分配存储空间
- C++中的const常量:可能分配存储空间:
- 当const常量为全局,并且需要在其它文件中使用
- 当使用&操作符对const常量取地址
- C++中的const常量类似于宏定义:const int c = 5;≈ #define c 5
- C++中的const常量与宏定义不同
- const常量由编译器处理,编译器对const常量进行类型检查和作用域检查
- 宏定义由预处理器处理,单纯的文本替换
#include <stdio.h>
void f()
{
#define a 3
const int b = 4; // b的作用域仅在f函数内
}
void g()
{
printf("a = %d\n", a);
//printf("b = %d\n", b); // error: 'b' was not declared in this scope
}
int main(int argc, char *argv[])
{
f();
g();
printf("Press enter to continue ...");
getchar();
return 0;
}
2.3 const常量的判别准则
- 只有用字面量初始化的const常量才会进入符号表
- 使用其它变量初始化的const常量仍然是只读变量
- 被volatile修饰的const常量不会进入符号表
- 在编译期间不能直接确定初始值的const标识符,都被作为只读变量处理。
- const引用的类型与初始化变量的类型
- 相同:初始化变量成为只读变量
- 不同:生成—个新的只读变量
#include <stdio.h>
int main()
{
const int x = 1;
const int &rx = x;
int &nrx = const_cast<int&>(rx);
nrx = 5;
printf("x = %d\n", x);
printf("rx = %d\n", rx);
printf("nrx = %d\n", nrx);
printf("&x = %p\n", &x);
printf("&rx = %p\n", &rx);
printf("&nrx = %p\n", &nrx);
volatile const int y = 2;
int* p = const_cast<int*>(&y);
*p = 6;
printf("y = %d\n", y);
printf("p = %p\n", p);
const int z = y;
p = const_cast<int*>(&z);
*p = 7;
printf("z = %d\n", z);
printf("p = %p\n", p);
char c = 'c';
char& rc = c;
const int& trc = c; //类型不同,新的只读变量
rc = 'a';
printf("c = %c\n", c);
printf("rc = %c\n", rc);
printf("trc = %c\n", trc);
return 0;
}
- 运行结果
2.4 小结
- 与C语言不同,C++中的const不是只读变量
- C++中的const是一个真正意义上的常量
- C++编译器可能会为const常量分配空间
- C++完全兼容C语言中const常量的语法特性
- 指针是—个变量
- 引用是一个变量的新名字
- const引用能够生成新的只读变量
- 在编译器内部使用指针常量实现“引用”
- 编译时不能直接确定初始值的const标识符都是只读变量
3. mutable关键字
- mutable是为了突破const函数的限制而设计的
- mutable成员变量将永远处于可改变的状态
- mutable在实际的项目开发中被严禁滥用
- mutable的深入分析
- mutable成员变量破坏了只读对象的内部状态
- const成员函数保证只读对象的状态不变性
- mutable成员变量的出现无法保证状态不变性
- 实例分析
- 统计对象中某个成员变量的访问次数
#include?<iostream>??
??
using?namespace?std;??
??
class?Test??
{??
????int?m_value;??
????mutable?int?m_count;??
public:??
????Test(int?value?=?0)??
????{??
????????m_value?=?value;??
????????m_count?=?0;??
????}??
??????
????int?getValue()?const??
????{??
????????m_count++;??//const成员函数,内部不能直接改变成员变量值??
????????return?m_value;??
????}??
??????
????void?setValue(int?value)??
????{??
????????m_count++;???
????????m_value?=?value;??
????}??
??????
????int?getCount()?const??
????{??
????????return?m_count;???
????}??
??
};??
??
int?main(int?argc,?char?*argv[])??
{??
????Test?t;??
??????
????t.setValue(100);??
??????
????cout?<<?"t.m_value?=?"?<<?t.getValue()?<<?endl;??
????cout?<<?"t.m_count?=?"?<<?t.getCount()?<<?endl;??
??????
????const?Test?ct(200);??
??????
????cout?<<?"ct.m_value?=?"?<<?ct.getValue()?<<?endl;??
????cout?<<?"ct.m_count?=?"?<<?ct.getCount()?<<?endl;??
??????
????return?0;??
}??
- 运行结果
- 更好的解决方案
#include?<iostream>??
#include?<string>??
??
using?namespace?std;??
??
class?Test??
{??
????int?m_value;??
????int?*?const?m_pCount;??
????/*?mutable?int?m_count;?*/??
public:??
????Test(int?value?=?0)?:?m_pCount(new?int(0))??
????{??
????????m_value?=?value;??
????????/*?m_count?=?0;?*/??
????}??
??????
????int?getValue()?const??
????{??
????????/*?m_count++;?*/????//只读对象内部不能直接改变??
????????*m_pCount?=?*m_pCount?+?1;??
????????return?m_value;??
????}??
??????
????void?setValue(int?value)??
????{??
????????/*?m_count++;?*/??
????????*m_pCount?=?*m_pCount?+?1;??
????????m_value?=?value;??
????}??
??????
????int?getCount()?const??
????{??
????????/*?return?m_count;?*/??
????????return?*m_pCount;??
????}??
??
????~Test()??
????{??
????????delete?m_pCount;??
????}??
};??
??
int?main(int?argc,?char?*argv[])??
{??
????Test?t;??
??????
????t.setValue(100);??
??????
????cout?<<?"t.m_value?=?"?<<?t.getValue()?<<?endl;??
????cout?<<?"t.m_count?=?"?<<?t.getCount()?<<?endl;??
??????
????const?Test?ct(200);??
??????
????cout?<<?"ct.m_value?=?"?<<?ct.getValue()?<<?endl;??
????cout?<<?"ct.m_count?=?"?<<?ct.getCount()?<<?endl;??
??????
????return?0;??
}??
内容总结
以上是互联网集市为您收集整理的C++深度解析(2)—C/C++中的const分析全部内容,希望文章能够帮你解决C++深度解析(2)—C/C++中的const分析所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。