【C++基础】——const是什么?什么时候用?与宏定义的区别

基础知识:
  1. 引用reference:
    引用:复合类型,相当于变量的另外一个名字,绰号,节省了拷贝带来的内存损耗,在实际程序中,主要用作函数的形式参数;

  2. 类class:
    理解成图纸,不占用内存,包括了成员变量和成员函数。对象是类的实例化,可以看成零件。

  3. 指针pointer:
    指针也是一种变量!指针的内容是地址!

〇、什么是const(必须知道的事情)?
  1. 简单理解:
    const的目的就是定义一个“不会被修改的常量”

  2. 可以修饰:
    变量、引用、指针,可以用于函数参数、成员函数修饰。成员变量。

  3. 作用:
    使用const可以减少代码出错的概率!避免magic number 以及增强程序的可读性。
    这个常量既可以防止程序其他地方不小心修改这个值,也能让程序员比较方便的调整这个值的大小。

  4. 与宏定于#define的区别:
    const有类型,可以进行类型检查,而宏定义没有。

  5. 常量指针和指针常量
    常量指针(指向常量的指针)
    指针常量(地址是常量,指针指向的地址不变

  6. Const值一旦创建后就不能修改,所以const对象必须初始化;

一、const的初始化:

const值一旦创建后就不能修改,所以const对象必须初始化。

const int i=0;//正确
const int i;//错误

const对象可以用非const对象初始化,也可以赋给非const对象,同时也能参与运算,只要初始化后不改变它的值就没问题。

int i;
const int j=i;//正确
int m=j;//正确
二、const的作用域:

默认状态下,const对象仅在文件内有效,不同文件的const对象不是同一个对象

文件之间可以共享的方法:可以使用extern来解决问题。

三、const与引用

const 引用是指向const的引用

  • 对常量的引用必须要用const
const int c=42;

int &r1 = c;      //错误,因为非常量引用可以改变所引用对象,所以这样不合理

const int &r2 = c; //正确,引用与对应的对象都是常量
四、 const与指针:

重要!重要!重要!
对着代码读:

  • 把星号*读作指针,
  • 把const读作常量
  • 非常容易!!!
    比如:
    const int* p就是——常量指针
    int* const p就是——指针常量
  1. 与常量引用相似,指向常量的指针必须要用const指针(指向常量的指针)
const int c=42;

int *r1=&c;      //错误

const int*r2=&c;//正确

*r2=42;//错误,不能给指针所指对象赋值
  1. 常量指针(指向const的指针)和指针常量(const指针)

区分

  • 常量指针(指向常量的指针),只能够读取内存中数据,却不能够修改内存中数据的属性的指针,称为指向常量的指针,简称常量指针。
  • 指针常量(地址是常量,指针指向的位置(地址)不变,指针本身是一个常量,但是指针指向的内容可以改变)

(前两个字作为形容词修饰后两个字。同时大家也要注意const指针这一说法,不要理解成常量指针)

Int num=0;

Int*const cur=#//一直指向num

Const double pi=3.1415;

Const double * const pip=π//指向常量的常量指针。

现在举例子说明一下常量指针域指针常量到底如何区分。

  1. int const* cur; 常量指针,指向常量的指针

2.Const int * cur; 常量指针,指向常量的指针

  1. int*const cur; 指针常量

  2. const(int *) cur; //错误,不可以这么写

辨识小技巧:
对着代码读,把星号读作指针,把const读作常量,非常容易。
Step1: const在星号*的前面,那么就是常量指针——“const前常量指针”
Step2: const在星号*的后面,那么就是指针常量——“const后指针常量”

五、 const与类:
  • const成员变量:
    类中声明变量为const类型。但是不可以初始化,必须要在构造函数初始化列表中初始化。
    这样的变量其实只是在一个对象中是不变的,要想在整个类中都不变就得用enum(枚举)

  • const成员函数:
    这样的成员函数不可以修改数据成员,如果修改成员变量或者调用了其他非const成员函数就会报错。

### C++ 模板元编程简介 **模板元编程(Template Metaprogramming, TMP)** 是一种利用C++编译期的模板机制来进行计算的技术。它是在编写程序时不直接通过运行时代码完成某些任务,而是借助于模板系统,在编译阶段生成特定功能的具体实现形式。这种方式可以在一定程度上优化性能并提高灵活性。 #### 主要特点 1. **基于类型的操作**:TMP允许开发者在编译期间处理复杂的逻辑判断和数值运算,主要是通过对不同类型做静态分析、条件选择以及递归展开等方式来达成目的。 2. **零成本抽象**:由于所有的操作都是发生在编译时期,因此不会增加额外的运行开销。当涉及到复杂算法或大量重复性的模式匹配工作时,可以显著提升效率。 3. **强类型安全性和泛化能力**:C++的模板本身就是一个高度通用化的工具集,结合强大的类型推导引擎,能够创建出既保持良好的类型检查又具备广泛适应范围的功能模块。 4. **延迟求值特性**:许多TMP技巧依赖于惰性求值的概念——即直到真正需要用到某个结果的时候才会触发对应的实例化进程。这一性质有助于简化一些难以控制副作用的情况下的编程难度。 5. **宏替代方案之一**:相比于传统的预处理器指令(例如`#define`),使用模板代替简单的常量定义或函数样式的宏往往能带来更清晰易懂且不易误用的设计风格。 #### 基本语法示例 最经典的例子就是斐波那契数列计算器: ```cpp // Fibonacci sequence computed at compile time via templates. template<int N> struct Fib { static const int value = Fib<N - 1>::value + Fib<N - 2>::value; }; template<> struct Fib<0> { // Base case for recursion termination. static const int value = 0; }; template<> struct Fib<1> { // Another base case to terminate the chain correctly. static const int value = 1; }; ``` 在这个例子中,我们利用特化版本终止了递归链条,并最终得到了想要的答案。这种做法不仅提高了可读性还保证了绝对的速度优势(毕竟所有的数学运算是完全免费地在构建过程中完成了!) #### 应用场景 - 类型特质查询; - 编译器内置属性检测; - 高效矩阵/向量库设计; - 自动派生辅助结构体等高级话题; 需要注意的是,虽然TMP确实很强大但它也存在一定的局限之处比如调试困难等问题。所以在实际应用当中应该权衡利弊谨慎选用合适的方法论解决问题!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值