首页 > 编程语言 >C++中const和constexpr的作用

C++中const和constexpr的作用

时间:2023-02-24 14:31:44浏览次数:30  
标签:const 常量 int C++ constexpr 修饰 表达式

目录

背景

const关键字

constexpr关键字

总结

背景

很多C++的初学者看到const这个关键字的第一反应都是一头雾水,主要是因为const可以出现在很多的位置,以及后面加入的constexpr更是常常感到困惑,今天就为大家一一解释出现它们的含义和以及作用

const关键字

1. const修饰变量

这是最基本的一种用法,顾名思义,就是将该变量修饰为常量,从而不可以修改。很多的全局变量都是通过常量来进行修饰,需要注意的是,使用const关键字修饰的变量需要立刻初始化

// 修饰局部变量,全局变量,成员变量
const int a = 2;
a = 3;	// 错误,表达式必须是可修改的左值,意思就是a是个常量,无法修改

// 还有人习惯这种写法,作用是一样的,看个人喜好即可
int const b = 22;

// 修饰函数参数
void test(const int num) {
    num = 3;	// 错误,表达式必须是可修改的左值,意思就是参数num是个常量,无法修改
}
2. 修饰指针

虽然指针也是一种变量,不过当const与指针出现在一起的时候,位置的不同会发生不同的作用,所以单独拎出来讲

// 第一种情况:指针常量
int a = 2;
const int *p = &a;	// const作用:使其无法通过指针来修改变量
*p = 3;	// 错误,表达式必须是可修改的左值
a = 4; // 正确
cout << *p << endl;	// 4
// 同样地,有人习惯这种写法,作用是一样的,看个人喜好即可
int const *p2 = &a;

// 第二种情况:常量指针
int a = 2;
int* const p = &a;	// const作用:使指针p无法指向其他变量
int b = 3;
p = &b;	// 错误,表达式必须是可修改的左值
3. 修饰函数

const用于修饰函数也是最困惑的地方,主要原因在于它可以出现在不同的地方,并且每一个都有不同的含义。接下来为一一为大家解释

// 修饰函数返回值,这种用法毫无意义,它的作用相当于将返回值修饰为了常量,但是返回值是一个将亡值,在返回之后要么赋值给了其他的变量,然后其他变量可以继续修改,要么就随着离开作用域而被释放内存。所以通常不会这么使用。
const int getNum() {
    return 3;
}

// 修饰成员函数,通常加在成员函数的末尾,作用声明该成员函数为只读函数,即无法修改任何成员变量的值
class Student {
   public:
    void test() const {
        member = 3;	// 错误,表达式必须是可修改的左值,因为member是成员变量,而test函数被const修饰过后无法修改成员变量
        int b = 3;
        b = 4;	// 正确
    }

   private:
    int member = 2;
};
4. const引用

这是const最常用的一种方式,通常用于函数的参数列表中,因为我们知道在C++中函数参数有3中传递方式,分别是值传递指针传递(或者叫地址传递),引用传递,前两种在传递时都会发成拷贝行为

指针本身也是一个变量,在32位操作系统下占用4个字节,64位系统占用8个字节,虽然的拷贝成本会低一点,但是在大量的调用过程中也比较可观

所以通常我们采用传递引用的方式,因为引用只是变量的一个别名,不占用内存,所以不会发生拷贝行为。但是引用传递有一个问题,那就是形参可以改变实参的值。所以为了避免意外修改导致实参的值发生改,通常会采用const加上引用的方式传递参数

void test(const Student &s) {
    ...
}

constexpr关键字

constexprC++11中引入的一个关键字,它的作用主要是用来修饰一些函数和变量,使其成为常量表达式,从而在编译器就可以进行计算,进一步提高程序运行期的效率

**常量表达式:**指的是有一个或多个常量组成的表达式,在实际开发中经常会接触到常量表达式,比如数组长度就必须是一个常量表达式

int arr[5];	//	正确,长度5是由1个常量组成的常量表达式
int arr2[3 + 4];	// 正确,长度3+4是由2个常量组成的常量表达式
int n = 10;
int arr3[n];	// 错误,长度n是由变量构成,不是常量表达式
1. 修饰变量

由此可以看出,只要是常量表达式,我们就可以通过constexpr来进行修饰,从而提高程序的效率,比如下面这样

contexpr int n = 2 + 2;	// 正确,2+2是常量表达式,n将会在编译器进行计算
int arr[n] = {11, 22, 33, 44};	// 正确,n是一个常量表达式
cout << arr[2] << endl;	// 33
2. 修饰普通函数

constexpr还可以用于修饰函数的返回值,在C++11中被constexpr修饰的函数只能是非void类型的函数,而且必须非常简短,通常只有一句return表达式。不过在后续的C++14/17/20标准中进一步的放宽了这了限制,都可以通过编译了

constexpr int test() {
    return 1 + 1;
}
3. 修饰构造函数

constexpr还可以用于修饰自定义类型,不过有一个前提条件,就是该自定义类型具有constexpr修饰的构造函数,并且该构造函数不能有具体实现,否则会编译报错

class Student {
   public:
    constexpr Student(const char* name, int age) : name_(name), age_(age) {}

    void print() const { cout << name_ << ' ' << age_ << '\n'; }

   private:
    const char* name_;
    int age_;
};

void test() {
    constexpr Student s{"zhangsan", 18};
    s.print();
}

总结

const可以修饰编译期和运行期的常量,而constexpr只能修饰编译期的常量

const在仍然可以通过const_cast类型转换来修改值,而constexpr是不可以修改的,其实可以将const理解为只读变量更符合其含义

const只能用于非静态成员函数,而constexpr可以和成员,非成员,构造函数一起使用

再有常量表示的场景,尽可能的加上constexpr来让编译期进行计算

但是大面积的constexpr也会面临相应的增加编译时间的风险

标签:const,常量,int,C++,constexpr,修饰,表达式
From: https://blog.51cto.com/u_15950321/6083914

相关文章

  • c++引用与结构
    引用非常适合用于结构和类,使用结构引用参数的方式与使用基本变量引用相同,只需在声明结构参数时使用引用运算符&即可。structfree_throws{stringname;intmode;in......
  • vscode配置C++文件简记
    今天终于把vscode配置好了,这个玩意跟大爷一样难伺候。我也懒得写博客记录过程了,太麻烦了。而且我已经耽误太长时间在这里了,不想再经历一次了。我这里简单记录一下我遇到的......
  • 如何在VC++ 6.0中实现拖动指令改变执行路径?
    前文提要:在VC6.0之后出现的VS系列开发工具都具有的调试功能:移动指针更改执行流,VC6不支持这个UI操作。调试程序暂停时,源代码或“反汇编”窗口边距处的黄色箭头标记要运......
  • c++中具有继承关系的隐式转换问题
    起因是群里有人问:   2,3,4是为什么。解答:2:2是因为B中的show(A)才是多态,Aa2=newB(),此时a2只有show(A)的多态,而面对的类型切割问题,在编译的时候派生类会将基类的多......
  • 使用C++实现Modbus CRC16检验相关内容
    使用C++实现ModbusCRC16检验相关内容ModbusCRC-16校验代码以下为ModbusCRC-16校验代码函数:其中参数int*crc_sum为校验返回值,分为两个字节;参数int*data_blk_ptr......
  • C++ primer 5th 第二章 变量和基本类型 阅读笔记
    第二章变量和基本类型第一节基本内置类型C++标准规定了算术类型尺寸的最小值,同时允许编译器赋予这些类型更大的尺寸。比如:类型含义最小尺寸bool布尔类型......
  • C++的内存模型
    C++的内存包含4个大区,它们分别是代码区、全局区、栈区和堆区。以下将对它们的分区进行进一步的阐述。代码区:对于一段代码,首先要经过编译之后生成可执行文件才能执行,在Wi......
  • C++学习(2)STL八股文
    1、STL实现原理及其实现STL提供了六⼤组件,彼此之间可以组合套⽤,这六⼤组件分别是:容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器。STL六⼤组件的交互关系:a.容......
  • C++问题集
    const函数名后,加const使类的成员函数,不能修改类内成员。mutable可以突破const限制!在函数后面加const只能在类的成员函数中实现!普通的函数是无法进行这样的操作的!vo......
  • C/C++图书管理系统[2023-02-23]
    C/C++图书管理系统[2023-02-23](辅修)高级语言程序设计课程设计图书管理系统设计并实现一个学校图书馆的图书管理系统。具体要求:1、 图书信息和借阅信息等保存在文本文......