C++略识 之关键字const

2024-08-24 09:18
文章标签 c++ 关键字 const 略识

本文主要是介绍C++略识 之关键字const,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、const修饰的变量必须进行初始化

-->一般数据类型const常量初始化

const int i = 10; //合法

const int j; //非法,导致编译出错

-->指针const常量初始化

int *p = new int();

const int *p  =q; //等价于 int const *p = q;

-->引用const常量初始化

int *p = new int();

const int *p  =q; //等价于 int const *p = q;

[注意]:const常量有数据类型,而宏常量(#define)没有数据类型。编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误。

2、const限定符声明的的变量具有只读属性

const int i = 10;

int j = 0;

// to do ...

i = j; //非法,导致编译出错

j = i; //合法

3、const相比较于define,可以避免不必要的内存分配

#defineSTRING "abcdefghijklmn\n" 

  const charstring[]="abcdefghijklm\n"; 

  ... 

 printf(STRING); //为STRING分配了第一次内存 

 printf(string); //为string一次性分配了内存,以后不再分配 

  ... 

 printf(STRING); //为STRING分配了第二次内存 

 printf(string); 

  ...

由于const定义常量从汇编的角度来看,只是给出了对应的内存地址, 而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。

4、是不是const的常量值一定不可以被修改呢?

非也!!!

const int i=0; 

int *p=(int*)&i; 

p=100;

通过强制类型转换,将地址赋给变量,再作修改即可以改变const常量值。说明了申明为常量的数据也可能被改变。

我这里补充的是不要对const 的滥用。强制绕过const 检查可能会引起运行错误。

把const int i=0 声明在函数内,能够达到你的目的;把const int i=0 声明为全局变量,虽然仍然能够用强制转换绕过编译器检查,但会引起运行错误。
可参考下例:

const int j=50;  
void main()  
{  const int i=0;  int *p=(int*)&i;  *p=100;   int *p2=(int *)&j;  *p2=200;  // runtime error  cout << &i << &j;  system("pause");  
}

5、必须分清楚是数值常量还是指针常量

int j=0; 

const int i=0; //i是常量,i的值不会被修改 

const int *p1=&i; //指针p1所指内容是常量,可以不初始化 

int * const p2=&j;//指针p2是常量,所指内容可修改 

const int * const p3=&i; //指针p3是常量,所指内容也是常量 

p1=&j; //不合法 左操作数包含“int *”类型 

*p2=100; //不合法  右操作数包含“int *const ”类型

[注意]:指向常量的指针并不能保证所指向的值不被改变。比如:

const int i=10;  
void main()  
{  const int j=20;  int k = 30;  const int * p1=&i;  const int * p2 = &j;  const int * p3 = &k;  // i=80; fail  // j= 20; fail  // *p3 = 50; fail  // 以上三种均未逃过编译器检查  k=80;   // succeed 逃过了编译器检查。 *p3 不行,但直接改k 允许。  system("pause");  
}

6、const修饰类的数据成员

class A  
{  const int size;  //to do…    
}

[注意]:const修饰的数据成员只在某个对象的生存周期内是常量,而对于整个类而言却是可变的。因为类可以创建多个对象,不同的对象其const修饰的数据成员的值可以不同。所以不能在类声明中初始化const数据成员,因为类的对象未被创建时,编译器不知道const 数据成员的值是什么。比如:

class A  
{  const int size = 100; //错误  int array[size]; //错误,未知的size  
}  

const数据成员的初始化只能在类的构造函数的初始化表中进行。要想建立在整个类中都恒定的常量,应该用类中的枚举常量来实现。比如:

class A  
{  //to do…  enum { size1=100, size2 = 200 };  int array1[size1];  int array2[size2];    
}  

[注意]:枚举常量不会占用对象的存储空间,他们在编译时被全部求值。但是枚举常量的隐含数据类型是整数,其最大值有限,且不能表示浮点数。

7、const在函数声明中的应用

在一个函数声明中,const 可以修饰函数的返回值,或某个参数;对于成员函数,还可以修饰是整个函数,比如:

void fun1(const A *a );    
const A fun2( );
void fun3( ) const; // fun3( )为某个类的成员函数

[注意]:调用函数的时候,用相应的变量初始化const常量,则在函数体中,按照const所修饰的部分进行常量化,比如:

void fun1(const A *a); //不能对传递进来的指针的内容进行改变,保护了原指针所指向的内容
void fun2(const A &a); //不能对传递进来的引用对象进行改变,保护了原对象的属性<a target=_blank name="OLE_LINK2" style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"></a>
<span style="font-family: Arial, Helvetica, sans-serif;  background-color: rgb(255, 255, 255);"><strong><span style="color: red;">[注意</span><span style="color: red;">]</span></strong></span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">:参数const通常用于参数为指针或引用的情况,且只能修饰输入参数;若输入参数采用“值传递”方式,由于函数将自动产生临时变量用于复制该参数,该参数本就不需要</span>
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">保护,所以不用const修饰。</span>

[小结]

--->对于非内部数据类型的输入参数,因该将“值传递”的方式改为“const引用传递”,目的是为了提高效率。例如,将void Func(A a)改为void Func(const A &a)。

--->对于内部数据类型的输入参数,不要将“值传递”的方式改为“const引用传递”。否则既达不到提高效率的目的,又降低了函数的可理解性。例如void Func(int x)不应该改为void Func(const int&x)。






这篇关于C++略识 之关键字const的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1102069

相关文章

如何高效移除C++关联容器中的元素

《如何高效移除C++关联容器中的元素》关联容器和顺序容器有着很大不同,关联容器中的元素是按照关键字来保存和访问的,而顺序容器中的元素是按它们在容器中的位置来顺序保存和访问的,本文介绍了如何高效移除C+... 目录一、简介二、移除给定位置的元素三、移除与特定键值等价的元素四、移除满足特android定条件的元

Python获取C++中返回的char*字段的两种思路

《Python获取C++中返回的char*字段的两种思路》有时候需要获取C++函数中返回来的不定长的char*字符串,本文小编为大家找到了两种解决问题的思路,感兴趣的小伙伴可以跟随小编一起学习一下... 有时候需要获取C++函数中返回来的不定长的char*字符串,目前我找到两种解决问题的思路,具体实现如下:

C++ Sort函数使用场景分析

《C++Sort函数使用场景分析》sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变,如果某些场景需要保持相同元素间的相对顺序,可使... 目录C++ Sort函数详解一、sort函数调用的两种方式二、sort函数使用场景三、sort函数排序

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

C/C++错误信息处理的常见方法及函数

《C/C++错误信息处理的常见方法及函数》C/C++是两种广泛使用的编程语言,特别是在系统编程、嵌入式开发以及高性能计算领域,:本文主要介绍C/C++错误信息处理的常见方法及函数,文中通过代码介绍... 目录前言1. errno 和 perror()示例:2. strerror()示例:3. perror(

kotlin中const 和val的区别及使用场景分析

《kotlin中const和val的区别及使用场景分析》在Kotlin中,const和val都是用来声明常量的,但它们的使用场景和功能有所不同,下面给大家介绍kotlin中const和val的区别,... 目录kotlin中const 和val的区别1. val:2. const:二 代码示例1 Java

C++变换迭代器使用方法小结

《C++变换迭代器使用方法小结》本文主要介绍了C++变换迭代器使用方法小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1、源码2、代码解析代码解析:transform_iterator1. transform_iterat

详解C++中类的大小决定因数

《详解C++中类的大小决定因数》类的大小受多个因素影响,主要包括成员变量、对齐方式、继承关系、虚函数表等,下面就来介绍一下,具有一定的参考价值,感兴趣的可以了解一下... 目录1. 非静态数据成员示例:2. 数据对齐(Padding)示例:3. 虚函数(vtable 指针)示例:4. 继承普通继承虚继承5.

C++中std::distance使用方法示例

《C++中std::distance使用方法示例》std::distance是C++标准库中的一个函数,用于计算两个迭代器之间的距离,本文主要介绍了C++中std::distance使用方法示例,具... 目录语法使用方式解释示例输出:其他说明:总结std::distance&n编程bsp;是 C++ 标准

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.