您当前的位置: 首页 >  c++

顺其自然~

暂无认证

  • 4浏览

    0关注

    1317博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

C++ const 详解

顺其自然~ 发布时间:2022-05-26 10:54:13 ,浏览量:4

前言:

const在C/C++中重要性很大,如果单纯理解为“常量”那就错了,这一篇总结一下C++中const的详细的用法。

一、const 修饰变量

它限定一个变量不允许被改变。使用const在一定程度上可以提高程序的安全性和可靠性。

const int a;            // a 代表一个常整型数
int const a;            // a 代表一个常整型数
const int *a;           // a 代表一个指向常整型数的指针,即a的值是可变的,但是*a是不能变的,函数的一些形参经常会用到
int * const a;          // a 代表一个常指针,即a的值是不可变的,但是*a是可变的
int const * a const;    // a代表的是一个指向常整型数的常指针

主要看const修饰的是什么?1、const + 类型 说明const修饰的是类型,想让类型为常量,也就是这个类型的值为常量。 例如const int *a; 本来是定义一个指针变量,指针变量所指向的值为int类型。const修饰int 类型,那也就是说这个int 类型的值为常量,也就是说指针指向的值为常量。2、const + 变量 说明const修改的变量,想让这个变量为常量。 例如int *const a; 本来是定义一个指针变量,指针变量所指向的值为int 类型。const修饰变量,那就是说这个指针变量为常量,不可变。指针所指向的int类型的值是可变的。3、const 与 指针

int a = 20;
const int * p = &a;

上面定义了一个常指针,指向的数据 a 是不变的。即不能修改 *p 的值。

*p += 1; //INVALID
cin >> *p; //INVALID

尝试修改 *p 的值,是不被允许的,因为p指向的为const 的值。 但是,如果修改a是可以的,因为a是普通变量。

a = 30; //VALID
const int a = 20;
int *p = &a; //INVALID

上面定义一个可变的指针,指向一个const 的值,这个是不允许的。可以想下,如果这里允许,那样可以修改a 的值,*p = 30; 这样a 的const状态就荒谬了。C++禁止将const 地址赋给非const 的指针。如果非要这样做,可以通过const_cast 强制转换。 这里修改为:

const int* p = &a; //VALID

如果将指针指向指针,则情况将更复杂一点。上面讲到如果是一级间接关系,可以将非const的指针赋给const的指针。例如,

int a = 10;
int *p = &a;
cont int *pt = p;

上面的操作都是允许的,只不过需要注意的是,*p 是可以修改的,但是*pt 就不能修改。 然而,进入二级间接关系时,与一级间接关系一样将const 和非const混合的指针赋值方式将不再安全。例如,

const int **p2;
int *p1;
const int a = 20;
p2 = &p1; //这里是不被允许的,编译的时候会报错
*p2 = &a;
*p1 = 10;

上面将非const 的指针p1的地址赋值给const 指针p2,因此可以使用p1来修改const数据。因此,仅当只有一层间接关系(如指针指向基本数据类型)时,才可以将非const 地址或指针赋给const 指针。4、尽可能的使用const 将指针参数声明为指向常量数据的指针有两个理由:   ● 这样可以避免由于无意间修改数据而导致的编程错误;   ● 使用const 使得函数能够处理const 和非const 实参,否则只能接受非const 数据。 例如, 有个常量数据array定义如下, const int array [] = {1, 2, 3, 4, 5}; 有个函数func定义如下, void func(int array[], int n) { ... } 将上面常量数组作为参数传入,是不允许的,需要将参数改为const。  

二、const 修饰函数

1、const 修饰函数参数 如果函数作为输出用,不论是什么数据类型,也不论采用指针传递还是引用传递,都不能加const 修饰,否则参数会失去输出功能。 const 只能修饰输入作用的参数。 如果输入参数为指针,加上const 之后起到保护指针意外修改的作用。 例如,

void StringCopy(char* strDest, const char* strSource);

这里strSource 加上const 修饰,就是为了防止strSource 会被意外的修改。实参中指针指向一段内存地址,调用函数之后,函数会产生一个临时指针变量,这个变量的地址肯定跟实参的指针地址不一样,但是这两指针指向的内存是同一块。形参加上const 修饰之后,保护了这一块内存地址不被修改,如果刻意修改这一块内存,编译器会报错。 如果输入参数为引用,加上const 之后不但起到了保护作用,也提高了程序效率。 例如,

void func(A a); //这里的A类型为用户定义的类型

这个函数在调用的时候会生成一个临时对象,而且会调用拷贝构造函数,函数结束还要析构。如果改成引用void func(A &a); 只是相当于实参的一个别名,不会产生临时变量。所以,如果是自定义类型,建议用引用作为函数形参。 但是,即使用引用,如果只是作为输入用,最好加上const 修饰,这样就不会改变实参的值,如果刻意修改,编译器会报错。所以,函数最后改成void func(const A& a); 当然,不是所有的数据类型都需要用应用,例如,

void func(int x);

对于内部类型的参数,不存在构造、析构的过程,产生临时变量、值的复制过程很快,无需用引用。2、const 修饰函数返回值 如果是值传递,没有必要将返回值用const 修饰,例如,

const int func();

函数的返回值为一个int 类型的值,这个只是个临时的值,没有必要用const 修饰,最终这个值会复制给接受它的变量。

如果返回值为引用,同上面形参,都可以提高效率。但是一般返回引用的地方并不是很多,一般会出现在类的赋值函数中。而且,用const 修饰返回值为引用类型的更少。

如果返回值为指针,加上const修饰之后,同样的内容是不能修改的。不过有一点需要注意,接受的变量也必须是const 修饰。例如,

const char* func();
char* str = func();

上面这样调用是不对的,需要将变量str 用const修饰,改为:const char* str = func();3、const  修饰成员函数 const 修饰的成员函数为了保护成员变量,要求const 函数不能修改成员变量,否则编译会报错。 声明的时候const放在函数最后,例如,

class MyClass {
public:
    void func(int x) const;
};

const 函数的几个规则: 1)const 对象只能访问const 成员函数,非const 的对象可以访问任何成员函数,包括const 成员函数。 2)如果函数名、参数、返回值都相同的const成员函数和非const成员函数是可以构成重载,那么const对象调用const成员函数,非const对象默认调用非const的成员函数。 3)const成员函数可以访问所有成员变量,但是只能访问const的成员函数。 4)非const成员函数,可以访问任何成员,包括const成员成员函数。 5)const成员函数不能修改任何的成员变量,除非变量用mutable修饰。 这一点可以理解为,在const的成员函数中成员变量都变成const属性,无法再次修改。如果函数的返回类型为此成员变量的引用,那必须也要加上const修饰。例如,

class MyClass {
public:
    int & func() const { return value; }
private:
    int value;
};

value为成员变量,func函数为const成员函数,如果要返回value的引用,这里的func函数返回值必须要加上const,改为,

const int& func() const { return value; }

当然,还有其他修改方法:   ● 把int value 改成mutable int value。mutable修饰的变量使之在const函数中可以被改变的   ● return value 改成。 return const_cast(value)。const_cast去掉了const性质。   ● 把引用去掉,写成返回值类型的。   ● 把函数后面的const去掉。   ● 返回值不是类的成员变量。            int& func() const{ int temp = value; return temp; }

三、实例说明
#include "test.h"
 
class Test9 {
public:
    Test9() : vTest1(1), vTest2(1) { cout             
关注
打赏
1662339380
查看更多评论
0.0467s