c++中const的使用详解_C 语言

Const 是C++中常用的类型修饰符,常类型是指使用类型修饰符const说明的类型,常类型的变量或对象的值是不能被更新的。

1、定义常量
(1)const修饰变量,以下两种定义形式在本质上是一样的。它的含义是:const修饰的类型为TYPE的变量value是不可变的。

 TYPE const ValueName = value;
     const TYPE ValueName = value;

(2)将const改为外部连接,作用于扩大至全局,编译时会分配内存,并且可以不进行初始化,仅仅作为声明,编译器认为在程序其他地方进行了定义.

     extend const int ValueName = value;

2、指针使用CONST
(1)指针本身是常量不可变
     (char*) const pContent;
     const (char*) pContent;

(2)指针所指向的内容是常量不可变
     const (char) *pContent;
     (char) const *pContent;

(3)两者都不可变
      const char* const pContent;

(4)还有其中区别方法,沿着*号划一条线:
如果const位于*的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;
如果const位于*的右侧,const就是修饰指针本身,即指针本身是常量。

3、函数中使用CONST

(1)const修饰函数参数
a.传递过来的参数在函数内不可以改变(无意义,因为Var本身就是形参)

void function(const int Var);

b.参数指针所指内容为常量不可变

void function(const char* Var);

c.参数指针本身为常量不可变(也无意义,因为char* Var也是形参)

void function(char* const Var);

d.参数为引用,为了增加效率同时防止修改。修饰引用参数时:

void function(const Class& Var); //引用参数在函数内不可以改变

void function(const TYPE& Var); //引用参数在函数内为常量不可变

2)const 修饰函数返回值
    const修饰函数返回值其实用的并不是很多,它的含义和const修饰普通变量以及指针的含义基本相同。
    a.const int fun1() //这个其实无意义,因为参数返回本身就是赋值。
    b. const int * fun2() //调用时 const int *pValue = fun2();
                          //我们可以把fun2()看作成一个变量,即指针内容不可变。
    c.int* const fun3()   //调用时 int * const pValue = fun2();
                          //我们可以把fun2()看作成一个变量,即指针本身不可变。

4、类相关CONST

(1)const修饰成员变量
const修饰类的成员函数,表示成员常量,不能被修改,同时它只能在初始化列表中赋值。
    class A
    {
        …
        const int nValue;         //成员常量不能被修改
        …
        A(int x): nValue(x) { } ; //只能在初始化列表中赋值
     }

(2)const修饰成员函数
const修饰类的成员函数,则该成员函数不能修改类中任何非const成员函数。一般写在函数的最后来修饰。
    class A
    {
        …
       void function()const; //常成员函数, 它不改变对象的成员变量.                       

//也不能调用类中任何非const成员函数。
}

(3)const修饰类对象/对象指针/对象引用

•const修饰类对象表示该对象为常量对象,其中的任何成员都不能被修改。对于对象指针和对象引用也是一样。
•const修饰的对象,该对象的任何非const成员函数都不能被调用,因为任何非const成员函数会有修改成员变量的企图。

例如:

复制代码 代码如下:

class AAA

    void func1(); 
  void func2() const; 

const AAA aObj; 
aObj.func1(); //×
aObj.func2(); //正确

const AAA* aObj = new AAA(); 
aObj-> func1(); //×
aObj-> func2(); //正确

5、将Const类型转化为非Const类型的方法

C++提供了四个转换运算符:

•const case <new type> (expression)
•static_cast <new_type> (expression)
•reinterpret_cast <new_type> (expression)
•dynamic_cast <new_type> (expression)
 

采用const_cast 进行非Const类型转换。 
用法:const_cast <type_id>  (expression)
该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和expression的类型是一样的。

•常量指针被转化成非常量指针,并且仍然指向原来的对象;
•常量引用被转换成非常量引用,并且仍然指向原来的对象;
•常量对象被转换成非常量对象。

复制代码 代码如下:

const int constant = 21;
const int* const_p = &constant;
int* modifier = const_cast<int*>(const_p);
*modifier = 7;

当然我们可以用下面的传统方式代替:

复制代码 代码如下:

const int constant = 21;
int* modifier = (int*)(&constant);

从前面代码中已经看到,我们不能对constant进行修改,但是我们可以对modifier进行重新赋值。

但是但是,程序世界真的混乱了吗?我们真的通过modifier修改了constatn的值了吗?修改const变量的数据真的是C++去const的目的吗?

如果我们把结果打印出来:

复制代码 代码如下:

cout << "constant: "<< constant <<endl;
cout << "const_p: "<< *const_p <<endl;
cout << "modifier: "<< *modifier <<endl;
/**
constant: 21
const_p: 7
modifier: 7
**/

constant还是保留了它原来的值。

可是它们的确指向了同一个地址呀:

复制代码 代码如下:

cout << "constant: "<< &constant <<endl;
cout << "const_p: "<< const_p <<endl;
cout << "modifier: "<< modifier <<endl;

/**
constant: 0x7fff5fbff72c
const_p: 0x7fff5fbff72c
modifier: 0x7fff5fbff72c
**/

虽然这样可以重新赋值const的值,但是绝对不要对const数据进行重新赋值。

时间: 2024-09-10 12:56:26

c++中const的使用详解_C 语言的相关文章

浅谈c++中的stl中的map用法详解_C 语言

Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道.这里说下map内部数据的组织,map内部自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处. 下面举例说明什么是一对一的数据映射.比如一个班级中,每个学生的学号跟他的姓名就存在着一一

C++中的const和constexpr详解_C 语言

C++中的const可用于修饰变量.函数,且在不同的地方有着不同的含义,现总结如下. const的语义 C++中的const的目的是通过编译器来保证对象的常量性,强制编译器将所有可能违背const对象的常量性的操作都视为error. 对象的常量性可以分为两种:物理常量性(即每个bit都不可改变)和逻辑常量性(即对象的表现保持不变).C++中采用的是物理常量性,例如下面的例子: struct A { int *ptr; }; int k = 5, r = 6; const A a = {&k};

C++编程中的格式化输出详解_C 语言

在输出数据时,为简便起见,往往不指定输出的格式,由系统根据数据的类型采取默认的格式,但有时希望数据按指定的格式输出,如要求以十六进制或八进制形式输出一个 整数,对输出的小数只保留两位小数等.有两种方法可以达到此目的.一种是使用控制符的方法:第2种是使用流对象的有关成员函数.分别叙述如下. 使用控制符控制输出格式 控制格式的使用方法这里不再赘述,仅举例说明 [例] 用控制符控制输出格式. #include <iostream> #include <iomanip>//不要忘记包含此头

c++ 中__declspec 的用法详解_C 语言

c++ 中__declspec 的用法如下,想要了解的继续往下看吧. 语法说明: __declspec ( extended-decl-modifier-seq ) 扩展修饰符: 1:align(#) 用__declspec(align(#))精确控制用户自定数据的对齐方式 ,#是对齐值. e.g __declspec(align(32)) struct Str1{ int a, b, c, d, e; }; 它与#pragma pack()是一对兄弟,前者规定了对齐的最小值,后者规定了对齐的最

C++ 中try finally关键字详解_C 语言

try-finally语句是Microsoft对C和C++语言的扩展,它能使32位的目标程序在异常出现时,有效保证一些资源能够被及时清除,这些资源的清除任务可以包括例如内存的释放,文件的关闭,文件句柄的释放等等.try-finally语句特别适合这样的情况下使用,例如一个例程(函数)中,有几个地方需要检测一个错误,并且在错误出现时,函数可能提前返回. #include <windows.h> #include <stdio.h> try-finally语句的语法与try-excep

C++中的Lambda表达式详解_C 语言

我是搞C++的 一直都在提醒自己,我是搞C++的:但是当C++11出来这么长时间了,我却没有跟着队伍走,发现很对不起自己的身份,也还好,发现自己也有段时间没有写C++代码了.今天看到了C++中的Lambda表达式,虽然用过C#的,但是C++的,一直没有用,也不知道怎么用,就可怜的连Lambda语法都看不懂.好了,这里就对C++中的Lambda进行一个简单的总结,就算是对自己的一个交代,我是搞C++的,我是一个C++ programmer. 一段简单的Code 我也不是文艺的人,对于Lambda的

C++中的RTTI机制详解_C 语言

前言 RTTI是"Runtime Type Information"的缩写,意思是运行时类型信息,它提供了运行时确定对象类型的方法.RTTI并不是什么新的东西,很早就有了这个技术,但是,在实际应用中使用的比较少而已.而我这里就是对RTTI进行总结,今天我没有用到,并不代表这个东西没用.学无止境,先从typeid函数开始讲起. typeid函数 typeid的主要作用就是让用户知道当前的变量是什么类型的,比如以下代码: 复制代码 代码如下: #include <iostream&g

C++中的RAII机制详解_C 语言

前言 在写C++设计模式--单例模式的时候,在写到实例销毁时,设计的GC类是很巧妙的,而这一巧妙的设计就是根据当对象的生命周期结束时会自动调用其析构函数的,而这一巧妙的设计也是有专业的名词的--RAII.那以下将围绕RAII,全面的讲解RAII的相关知识. 什么是RAII? RAII是Resource Acquisition Is Initialization的简称,是C++语言的一种管理资源.避免泄漏的惯用法.利用的就是C++构造的对象最终会被销毁的原则.RAII的做法是使用一个对象,在其构造

深入uCOS中全局变量的使用详解_C 语言

在C语言编程中经常会遇到全局变量.全局变量的定义一般采用下面的方式 .C文件中定义 unsigned int gVariable; .h文件中声明 extern unsigned int gVariable; 这样做的目的是防止变量重复声明,提高编译效率.但是如果这样的定于如果安排不好就会出现各种各样的问题.在编译时重复的声明,甚至出现错误. 阅读邵贝贝翻译的<uC/OS-II>一书,发现里面用了一种非常巧妙的全局变量定义的方法,下面就自己的理解做一下记录,算是自己的笔记.也写出来和大家共同学