C++ const的各种用法详解

 更新时间:2023年04月23日 09:37:07   作者:COS  
const名叫常量限定符,用来限定特定变量,以通知编译器该变量是不可修改的。习惯性的使用const,可以避免在函数中对某些不应修改的变量造成可能的改动。本文主要谈谈const的用法,感兴趣的同学可以参考阅读

C++作为一种面向对象的经典语言,它是非常的强大,它的每个部分都值得我们去深入了解。

const的基本概念:

const名叫常量限定符,用来限定特定变量,以通知编译器该变量是不可修改的。习惯性的使用const,可以避免在函数中对某些不应修改的变量造成可能的改动。

下面我就const的用法来谈谈:

const的用法大致可分为以下几个方面:

(1)const修饰基本数据类型

(2)const应用到函数中

(3)const在类中的用法

(4)const修饰类对象,定义常量对象 

一、const修饰基本数据类型 

1.const修饰一般常量及数组  

  const int a=10;               等价的书写方式:     int const a=10;
          const int arr[3]={1,2,3};                        int const arr[3]={1,2,3};

对于类似这些基本数据类型,修饰符const可以用在类型说明符前,也可以用在类型说明符后,其结果是一样的。在使用这些常量的时候,只要不改变这些常量的值便好。  

2.const修饰指针变量*及引用变量&         

介绍本部分内容之前,先说说指针和引用的一些基本知识。

指针(pointer)是用来指向实际内存地址的变量,一般来说,指针是整型,而且一般的大家会接受十六进制的输出格式。
引用(reference)是其相应变量的别名,用于向函数提供直接访问参数(而不是参数的副本)的途径,与指针相比,引用是一种受限制的指针类型,或者说是指针的一个子集,而从其功能上来看,似乎可以说引用是指针功能的一种高层实现。

关于运算符&和*:
在C++里,沿袭C中的语法,有两个一元运算符用于指针操作:&和*。按照本来的定义,&应当是取址符,*是指针符,也就是说, &用于返回变量的实际地址,*用于返回地址所指向的变量,他们应当互为逆运算。实际的情况也是如此。

在定义变量的引用的时候,&只是个定义引用的标志,不代表取地址。

举例:  

 #include<iostream.h>
  void main()
 {
      int a;  //a is an integer
      int *aPtr;  //aPtr is a pointer to an integer
  
     a=7;
     aPtr = &a;
     cout<<"Showing that * and & are inverses of "<<"each other.\n";
     cout<<"a="<<a<<"  *aPtr="<<*aPtr<<"\n";
     cout<<"&*aPtr = "<<&*aPtr<<endl;
     cout<<"*&aPtr = "<<*&aPtr <<endl;
 }

运行结果: 

了解完指针和应用的基本概念之后,下面继续我们的话题。

const修饰指针(*):

const int* a = & [1]          //非常量数据的常量指针    指针常量
int const *a = & [2]          //非常量数据的常量指针     a is a pointer to the constant char variable
int* const a = & [3]          //常量数据的非常量指针指针常量 常量指针 a is a constant pointer to the (non-constant) char variable
const int* const a = & [4]    //常量数据的常量指针

可以参考《Effective c++》Item21上的做法,

如果const位于星号*的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;

如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量。

因此,[1]和[2]的情况相同,都是指针所指向的内容为常量,这种情况下不允许对内容进行更改操作,如不能*a = 3 ;

[3]为指针本身是常量,而指针所指向的内容不是常量,这种情况下不能对指针本身进行更改操作,如a++是错误的;

[4]为指针本身和指向的内容均为常量。   

const修饰引用(&):

 int const &a=x;
   const int &a=x;
   int &const a=x;//这种方式定义是C、C++编译器未定义,虽然不会报错,但是该句效果和int &a一样。   

这两种定义方式是等价的,此时的引用a不能被更新。如:a++ 这是错误的。   

二、const应用到函数中  

1.作为参数的const修饰符

2.作为函数返回值的const修饰符  

其实,不论是参数还是返回值,道理都是一样的,参数传入时候和函数返回的时候,初始化const变量
1修饰参数的const,如 void fun0(const A* a ); void fun1(const A& a);
 调用函数的时候,用相应的变量初始化const常量,则在函数体中,按照const所修饰的部分进行常量化,如形参为const A* a,

则不能对传递进来的指针的内容     进行改变,保护了原指针所指向的内容;如形参为const A& a,则不能对传递进来的引用对象进行改变,

保护了原对象的属性。
[注意]:参数const通常用于参数为指针或引用的情况; 
2修饰返回值的const,如const A fun2( ); const A* fun3( );
这样声明了返回值后,const按照"修饰原则"进行修饰,起到相应的保护作用。

const Rational operator*(const Rational& lhs, const Rational& rhs)
{
return Rational(lhs.numerator() * rhs.numerator(),
lhs.denominator() * rhs.denominator());
}

返回值用const修饰可以防止允许这样的操作发生:

Rational a,b;
Radional c;
(a*b) = c;

一般用const修饰返回值为对象本身(非引用和指针)的情况多用于二目操作符重载函数并产生新对象的时候。

类中的成员函数:A fun4()const; 其意义上是不能修改所在类的的任何变量。 

三、类中定义常量(const的特殊用法) 

在类中实现常量的定义大致有这么几种方式实现: 

1.使用枚举类型 

class test
{
     enum { SIZE1 = 10, SIZE2 = 20}; // 枚举常量
     int array1[SIZE1];  
     int array2[SIZE2];
};

2.使用const 

不能在类声明中初始化const数据成员。以下用法是错误的,因为类的对象未被创建时,编译器不知道SIZE的值是什么。 

  class test
  {
        const int SIZE = 100;     // 错误,企图在类声明中初始化const数据成员
        int array[SIZE];          // 错误,未知的SIZE
  };

正确的使用const实现方法为:const数据成员的初始化只能在类构造函数的初始化表中进行。 

class A
 {…
        A(int size);      // 构造函数
        const int SIZE ; 
 };
 A::A(int size) : SIZE(size)    // 构造函数的初始化表
{
      …
}
//error 赋值的方式是不行的
A::A(int size)
{
     SIZE=size;
}
void main()
{
    A  a(100); // 对象 a 的SIZE值为100
    A  b(200); // 对象 b 的SIZE值为200
}

注意:对const成员变量的初始化,不能在变量声明的地方,必须在类的构造函数的初始化列表中完成,即使是在构造函数内部赋值也是不行的。

具体原因请参见 【初始化列表和赋值的区别】 

3.使用static const 

通过结合静态变量来实现:

#include<iostream.h> 
class Year
{ 
private:
 int y; 
public:
 static int const Inity;
public: 
 Year()
 {
  y=Inity;
 }
 };
int const Year::Inity=1997;//静态变量的赋值方法,注意必须放在类外定义
void main()
{
 cout<<Year.Inity<<endl;//注意调用方式,这里是用类名调用的。
}

到这里就把在类中定义常量的方法都陈列出来了。 

四、const定义常量对象,以及常量对象的用法

class test
{
public:
    test():x(1)
    {
        y=2;
    }
    ~test()
    {}
    void set(int yy)
    {
        y=yy;
    }
    int getx() const
    {
        return x;
    }
//protected:
    const int x;
    int y;
};
void main()
{
 const test t;
 t.set(33);//error
 t.getx();
}

常量对象只能调用常量函数,别的成员函数都不能调用。 

五、使用const的一些建议  

<1>要大胆的使用const,这将给你带来无尽的益处,但前提是你必须搞清楚原委;
<2> 要避免最一般的赋值操作错误,如将const变量赋值,具体可见思考题;
<3> 在参数中使用const应该使用引用或指针,而不是一般的对象实例,原因同上;
<4> const在成员函数中的三种用法(参数、返回值、函数)要很好的使用;
<5>不要轻易的将函数的返回值类型定为const;
<6>除了重载操作符外一般不要将返回值类型定为对某个对象的const引用; 

参考资料:

(1)继续C++——指针,引用和常量限定符const           

http://blog.csdn.net/jarodwen/archive/2006/12/19/1449568.aspx  

(2)C++中const用法总结                                         

http://lanmh.iteye.com/blog/796410

(3)常量函数、常量引用参数、常量引用返回值[C++]    

http://www.cnblogs.com/JCSU/articles/1045801.html

(4)const使用详解                                                   

http://www.vckbase.com/document/viewdoc/?id=412

(5)c/c++中const用法总结                               

http://www.newsmth.net/pc/pccon.php?id=10002714&nid=359712

(6)高质量C++/C编程指南                                    http://fanqiang.chinaunix.net/a4/b2/20020717/060200270.html

(7) Effective C++笔记—构造函数赋值VS初始化列表  http://blog.csdn.net/lifeisbetter/archive/2009/12/29/5099085.aspx

(8)初始化列表与构造函数内赋值

以上就是C++ const的各种用法详解的详细内容,更多关于C++ const用法的资料请关注脚本之家其它相关文章!

相关文章

  • 深入分析C++中声明与定义的区别

    深入分析C++中声明与定义的区别

    C++学了这么多年你知道为什么定义类时,类的定义放在.h文件中,而类的实现放在cpp文件中。它们为什么能够关联到一起呢?你知道什么东西可以放在.h文件中,什么不能。什么东西又可以放在cpp文件中。如果你忘记了或是压根就不明白,那么读过此文你会清晰无比!!
    2014-09-09
  • C语言使用posix正则表达式库的实现

    C语言使用posix正则表达式库的实现

    在C语言中,你可以使用 POSIX 正则表达式库(regex.h)来进行正则表达式的模式匹配,本文主要介绍了C语言使用posix正则表达式库的实现,具有一定的参考价值,感兴趣的可以了解一下
    2023-12-12
  • C++将二叉树转为双向链表及判断两个链表是否相交

    C++将二叉树转为双向链表及判断两个链表是否相交

    这篇文章主要介绍了C++将二叉树转为双向链表及判断两个链表是否相交的方法,文中还给出了求两个链表相交的第一个节点列的实现方法,需要的朋友可以参考下
    2016-02-02
  • C++映像劫持后门实例分析

    C++映像劫持后门实例分析

    这篇文章主要介绍了C++映像劫持后门,实例分析了C++映像劫持后门的原理与相关实现技巧,有助于进一步了解后门的原理,需要的朋友可以参考下
    2015-04-04
  • 浅谈MFC 改变控件大小和位置

    浅谈MFC 改变控件大小和位置

    在用VC开发应用程序时,经常会要做一些可以改变大小的对话框,而这个时候就要求对话框上的控件会随着对话框大小的改变而改变自己的位置和大小。下面我们就来探讨下在MFC中如何改变控件大小和位置
    2015-06-06
  • C++ vector在多线程操作中出现内存错误问题及解决

    C++ vector在多线程操作中出现内存错误问题及解决

    这篇文章主要介绍了C++ vector在多线程操作中出现内存错误问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • 使用VS Code的开发环境配置教程图文详解

    使用VS Code的开发环境配置教程图文详解

    这篇文章主要介绍了使用VS Code的开发环境配置教程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-05-05
  • 基于Matlab绘制小提琴图的示例代码

    基于Matlab绘制小提琴图的示例代码

    这篇文章主要介绍了如何利用Matlab实现小提琴图的绘制,文中的示例代码讲解详细,对我们学习Matlab有一定的帮助,需要的可以参考一下
    2022-05-05
  • C++中的RAII机制详解

    C++中的RAII机制详解

    这篇文章主要介绍了C++中的RAII机制详解,RAII是Resource Acquisition Is Initialization的简称,是C++语言的一种管理资源、避免泄漏的惯用法,需要的朋友可以参考下
    2014-09-09
  • C++中新手容易犯的十种编程错误汇总

    C++中新手容易犯的十种编程错误汇总

    一段C语言代码,在编译、链接和运行的各个阶段都可能会出现问题,下面这篇文章主要给大家介绍了关于C++中新手容易犯的十种编程错误的相关资料,需要的朋友可以参考下
    2021-10-10

最新评论