const用法->学习日记

const用法

const是c++的一个关键字,C语言也采用了const关键字,但是完全没有发挥出const的作用,const主要是在c++中被广泛采用。

  • const的作用:

    • const的最开始的被主要是被用来代替define,因为define有很多弊端,例如只能在预处理阶段进行代替,代替的数据并没有类型信息,对代码维护很不友好,而且没有类型检查功能。而const则解决了这些功能,当然只是在c++里,在C语言里,const与c++有很大的差别。#define N 10const int N = 10;实现的功能基本相同,只不过define在预处理阶段完成,const在编译阶段由c++编译器完成。
    • const既然是常量,显然可以用于保证代码的安全性,在明知道在变量生命周期内是不变的时候可以加上const设为常量,避免外界代码改变变量的值。
  • const的用法:
    调用const的最简单语法就是const int a = 0;在c++中const默认是内部连接 ,即只能在当前文件内使用a这个常量。
    关键点:

    • 在上面这个语法中的常量必须要初始化。
    • 此语法在编译器中并不为他分配存储空间,而是把这个定义存储在符号表里。
    • 在使用时会进行常量折叠。类似宏替换。
      较为明显的特征就是char c[a];是符合语法的。如果是a是变量的话,是不能用来声明数组的。

当然并不是只要是const修饰的变量就不分配内存,当需要用到这个变量的地址时例如

	int address = & a;
	int & b = a;

或者是加上extern修饰时

extern int a = 0;

都会强制编译器为a分配内存。
分配内存会影响常量折叠,但不是绝对的。
比如

const int a = 100;
int address = &a;
int b[a];

这仍然是合理的,因为虽然取地址会强制为a分配内存,但是在之前编译器已经认识i是一个常量且值为一百,已经将他加入符号表中。所以仍然可以。
如果是

const int a[] = {1,2,3};
int b[a[1]];

就不合理,因为此时编译器并不会将一个数组作为一个常量并加入如符号表中。所以编译器只会为a分配不可改变的存储空间。所以a[i]并不会进行常量折叠。
加上extern后还有一些其他的额外用法
首先extern修饰后在文件外也可以用这个常量。
分为初始化和不初始化两种:
初始化

extern int a = 0;

初始化的情况下在本文件中依然可以进行常数折叠。
不初始化

extern const int a;

不初始化的情况下本文件中不能进行常熟折叠。虽然是const但是仍然可以,这里看成是声明,而且需要在外部实现定义。
除了基本的int 、float、char、double类型const还可以和指针、函数、类结合在一起用,非常容易混淆

  • 与指针一起用:
    可以组成指向常量的指针和常量指针
    • 指向常量的指针:
const int *a;
int const *a;
  • 常量指针:
int a = 1;
int * const address = &a;//首先常量指针必须赋初值,这与前面是一样的。

可以总结为const总是优先修饰前面的变量类型,如果前面没有才修饰后边的。
结合起来有

const int a; //这里即使是非const的变量也可以进行下面的赋值。
int const * const address1 = &a;
const int * const address2 = &a;
  • 与函数一起用
    • 作为参数
      值传递的话其实并没有太大的意义,只是防止函数对副本的改变,倒不如在函数内部约定。
      指针地址传递的话可以防止对原变量的修改。
    • 作为返回值
      对于内建变量(int 、float、char、double)无关紧要,因为返回时也是返回的副本,但是const只要求原变量不变。但是对于自建类就有区别,返回的const值必须不能复制、不能修改。还需要注意的重点是临时量。
class A
{
public:
int a;
X(int a1 = 0){a = a1};
};
A f1()
{
return A();}
A f2(A &x)//这里只能是接受const的引用,指针不行,因为指针必须明确接受地址,而下面调用明显是直接传给他临时对象。
{
return x;
}
f2(f1());

在f2(f1());中f1()的返回值虽然不是const但是为了将返回值传递给f2();会创建临时量,而这个临时量由于只有系统管理人无法获得或改变,所以默认const,传给f2()是付给了一个非const,所以就会报错。

  • 与类一起用
    • 类里的常量
      类里面的常量并不能进行常量折叠,而是像C语言中const的用法一样就是不能被更改的存储空间。每一个类对象都有这样一个常量,但是常量的值可以不同,所以在声明const成员是不能初始化。类里const成员的初始化要在构造函数的初始化列表里初始化,因为初始化列表是在构造函数体执行前完成的。
      如果想要实现常量折叠,需要在加上static静态关键字,static意味着这个常量并不为某个对象所独有,所有该类的对象共同拥有这个常量,而且值相等。此时需要在类的定义的时候就初始化,而不是创建对象时才初始化。
  • const类和const成员函数
    由于const成员函数的出现于const类有很密切的联系,所以放在一起说。
    const函数的作用要从const类说起,const类要求所以数据成员在对象的存在周期内不得改变,所以这个对象只被允许调用那些不改变对象内数据成员的成员函数,为了编译器识别出这些函数,我们必须用const标记成员函数。语法为:
class A{
public:
int a;
A(int a1 = 0):a(a1); //构造函数和析构函数不是const类型的,因为这两个函数都是默认会改变类的数据成员的。
int geta() const;
};
int geta() const
{return a;}

为区分返回为const,const需放在函数后面。而且定义是也必须加上const否则视为不同的函数。
注意:const成员函数不能以任何方式改变数据成员,也不可调用非const成员函数
为了增强代码的灵活性,有时const对象也不一定是都不变的,也可能是大部分不变但是一少部分需要改变。所以有mutable关键字。加上mutable关键字的数据成员可以在const对象的const成员函数中改变。

附:

volatile与const的语法一样,意思是在编译器认识的范围外,这个数据是可以改变的。
const在c++与在c中的差别:
在c中const只是一个不能改变的存储空间。
在c++中有了更多的可能,也可以和一样,也可以分配了空间但是仍然可以常量折叠,也可以不分配空间进行常量折叠。除此之外还有与类的组合应用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

自律懒人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值