本文主要是介绍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进一步思考的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!