const和constexpr进一步思考

2024-05-30 02:04

本文主要是介绍const和constexpr进一步思考,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言:

        首先如果你对constexpr不了解,还是不太合适.

        这篇文章主要还写我自己在用constexpr遇到的一些疑问.

const比constexpr更加灵活

普通全局变量:

首先,一般的普通全局变量在程序的运行时进行初始化。具体地说,它们在程序进入main函数之前的启动阶段被初始化。也就是在编译期间不会确定值.

constexpr-编译时常量:

        一定是编译期确定变量的值.

constexpr-运行时常量:

        一定会报错,它只能编译期来确定值.

const-编译时常量:

        const int x = 5; // 编译时常量

const-运行时常量:

        const int y = time(nullptr);//正常运行!!

        //constexpr int y = time(nullptr);//报错!!

从上面看出,const比constexpr更加灵活!const既可以编译的时候来确定值,在不能编译时期确定的情况下,可以在运行时期确定变量的值.那么constexpr还有什么要引入的必要吗?

两者几乎不都等价了?

那么普通的全局变量是什么时候确定值?

拓展一下:

  • 普通全局变量在程序的运行时进行初始化。具体地说,它们在程序进入main函数之前的启动阶段被初始化。

const和constexpr几乎等价吗?

几乎等价,但是他又区别!

c++11,引入了constexpr想做的事,是在继承了const在编译期间的特性之后,增加一些功能!

而这个功能就是增加了对函数在编译期间确定值,也就是为什么这个关键字是const+expr组成,非常的贴切!

多说一句;expr的翻译就是表达式.c++中对于'表达式'这个词语的表达包括了变量和函数.

修饰变量的时候,constexpr几乎和const等价.都是编译期间对变量进行确定值.也就是constexpr中的const.

同时.在编译期间可以对函数确定值.也就是constexpr中的expr.

constexpr和const的作用域

普通全局变量:

        范围是所有的cpp文件,只要你加了extern就可以引用.

        非const全局变量具有外部链接。外部链接意味着这个变量在整个程序中是可见的。因此,如果在多个翻译单元中定义了相同名称的非const全局变量,链接器会检测到重复定义并报错。

const:

        范围只本cpp文件中.所以不同文件中相同的变量名不会造成重复.所以用extern引用就报错.

        const全局变量具有内部链接.每个翻译单元都有自己的独立副本,不会与其他翻译单元中的同名变量冲突。

constexpr:

        范围只本cpp文件中.所以不同文件中相同的变量名不会造成重复.

        这个同理const.

既然两者范围都是本文件,那么等同于加了static吗?

如果单纯从作用范围来看,是一样的.

但是static还有其他的属性,这些属性是要保留的.

比如修饰静态变量的时候,生命周期该怎么来就怎么来了.

如何在其他文件引用constexpr修饰的函数呢?

1:声明放在头文件,实现放在源文件

        不行!只能放在头文件中

2:直接放在头文件中实现(推荐)

        也可以直接在头文件中定义constexpr函数,以便编译器更好地进行内联优化。

        我在vs2017上试了,没问题.

// math.h
#ifndef MATH_H
#define MATH_H// 在头文件中定义 constexpr 函数
constexpr int factorial(int n) {return (n <= 1) ? 1 : (n * factorial(n - 1));
}#endif // MATH_H// main.cpp
#include <iostream>
#include "math.h"int main() {constexpr int fact5 = factorial(5); // 使用 constexpr 函数std::cout << "Factorial of 5: " << fact5 << std::endl;return 0;
}

如何在其他文件引用constexpr修饰的变量呢?

1:头文件中定义constexpr变量

        通常,如果你希望在多个翻译单元中使用同一个constexpr变量,最好将其定义在头文件中,并且通常使用inline关键字(c++17)来确保它具有外部链接且避免重复定义错误。

// config.h
#ifndef CONFIG_H
#define CONFIG_H// 在头文件中定义 inline constexpr 变量
inline constexpr int BUF_LEN = 100;#endif // CONFIG_H// main.cpp
#include <iostream>
#include "config.h"int main() {std::cout << "Buffer length: " << BUF_LEN << std::endl;return 0;
}

2:定义在源文件中,加extern,可能是不行的.

        为了在多个翻译单元中引用constexpr变量,应在头文件中使用inline constexpr进行定义.

        如果尝试用extern关键字声明constexpr变量,会导致编译错误,因为constexpr变量的默认行为是内部链接性,不能在另一个翻译单元中找到其定义。

c++17中引入inline的新特性

一般来说,我们在头文件中定义了变量,这个头文件被引用了多次,就会报'多重定义'的问题,

这个时候inline就可以解决这个问题.,使用inline关键字可以避免这种链接错误,因为它允许多个翻译单元共享同一个内联函数的副本。

这篇关于const和constexpr进一步思考的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1015269

相关文章

c++的初始化列表与const成员

初始化列表与const成员 const成员 使用const修饰的类、结构、联合的成员变量,在类对象创建完成前一定要初始化。 不能在构造函数中初始化const成员,因为执行构造函数时,类对象已经创建完成,只有类对象创建完成才能调用成员函数,构造函数虽然特殊但也是成员函数。 在定义const成员时进行初始化,该语法只有在C11语法标准下才支持。 初始化列表 在构造函数小括号后面,主要用于给

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

【编程底层思考】详解Java的JUC多线程并发编程底层组件AQS的作用及原理

Java中的AbstractQueuedSynchronizer(简称AQS)是位于java.util.concurrent.locks包中的一个核心组件,用于构建锁和其他同步器。AQS为实现依赖于FIFO(先进先出)等待队列的阻塞锁和相关同步器提供了一套高效、可扩展的框架。 一、AQS的作用 统一同步状态管理:AQS提供了一个int类型的成员变量state,用于表示同步状态。子类可以根据自己

一道算法题引发的动态内存管理的思考

在做PKU2762时,需要建邻接表。 于是按部就班写了下面一个插入边到邻接表中的函数: const int VMAX = 1010;typedef struct Graph{int vex;Graph* next;}Graph;Graph ArcGraph[VMAX];void insert(int u, int v){Graph* t = new Graph;Graph*

go 和 java 技术选型思考

背景:       go和java我这边自身都在使用,感受比较深,java使用了有7年多,go也就是今年开始的,公司需要所以就学了使用,发现这两个语言都很好,需要根据场景选择,我写下我这边的看法。 关于go和java语言层面和特性就不说了,网上都有,我这边从我这边实际使用的场景情况来说,供大家参考。 给我最大的感受,php转go的不少,也是符合未来技术大趋势的,目前来看,java转go也比较

思考自己写博客的意义

感想 从今年2月份开始,我就要求自己以每周4篇的速度写博客。然而问题是:每周的空闲时间是不稳定的,这导致我没法保证花费相同的时间去输出稳定质量的博客。当时间不够时,我将面临选择:是减少数量来保证稳定的质量,还是降低质量来保证稳定的数量? 我选择的是——牺牲质量。因为,相比于“质量”,“数量”是准确可见的。我担心:一旦有一次没能完成目标数量,便会出现“破窗效应”,让我潜意识里再也不认同“目标”了

s let 和const的区别 ,它们可以变量提升吗

在 JavaScript 中,let 和 const 是 ES6 引入的新变量声明关键字,它们与之前的 var 关键字相比,有几个重要的区别。特别是关于变量提升(hoisting)的行为不同。 变量提升(Hoisting) 在 JavaScript 中,“变量提升”是指变量声明会被提升到作用域的顶部,但变量的初始化不会。这意味着你可以先使用变量,然后再声明它。然而,let 和 const 的行

是时候重新思考你的Google广告策略了吗?

以产品为中心、仅以关键词为焦点的广告活动是 谷歌广告中常见的一种活动类型。 如果你销售复古女式T恤,你可能会设置基于“复古女式T恤”关键词的独立关键词广告活动。 对于许多B2C零售商来说,这种方法效果不错。但是,对于其他一些商家来说,基于产品和关键词的广告活动并不一定是最好的策略。 比如说,我们接手了一个新的B2B客户的谷歌广告账户,其所有广告活动都是以产品为中心、仅关注关键词的广告活动。

C++中const关键字的使用方法,烦透了一遍一遍的搜,总结一下,加深印象!!!

之前一直在学习C/C++,关于const的使用,这里出现一点,那里出现一点。知识用时方恨少,这一段时间正好各种笔试题,其中关于const的用法也是层出不穷,所以疲于在书本上各种翻,这里汇总一下,加深自己的印象的同时,也方便以后查阅和学习。菜鸟一个,若有错误,望指正! const关键字 常类型是指使用类型修饰符const说明的类型,常类型的变量或对象的值是不能被更新的。不管出现在任何上