constexpr和static constexpr全局变量之间的区别

时间:2017-08-31 18:02:22

标签: c++ c++11 constexpr linkage

在C ++ 11标准中,constexprstatic constexpr全局变量在标题中定义时有什么区别?更具体地说,当多个翻译单元包含相同的标题时,哪个声明(如果有的话)可以保证在翻译单元中定义相同的变量?

如,

cexpr.h:

#ifndef CEXPR_H
#define CEXPR_H

constexpr int cint = 1;
static constexpr int scint = 1;

#endif

a.cpp:

#include "cexpr.h"

b.cpp:

#include "cexpr.h"

2 个答案:

答案 0 :(得分:10)

在您当前的示例中没有区别:在变量声明中,constexpr暗示const,并且命名空间范围内的const变量默认具有内部链接(因此添加static不会改变任何事情。)

在C ++ 14中,您不能将变量声明为constexpr并让它具有外部链接,除非您只在一个翻译单元中执行此操作。原因是constexpr变量需要初始化程序,而初始化程序的声明是一个定义,并且您只能有一个定义。

但是,可以做的是使用正常的整数常量,您可以将其声明(未定义)为extern,并且在定义它的翻译单元中它甚至可以用作常量表达式:

<强> lib.h:

extern const int a;

<强> lib.cpp:

#include "lib.h"

const int a = 10;

int b[a] = {1, 2, 3};   // OK in this translation unit

在C ++ 17中,有一个新功能“内联变量”可以让你说:

inline constexpr int a = 10;

这是一个可以重复出现的“内联定义”,每个定义都定义了相同的实体(就像语言中所有其他“内联”实体一样)。

答案 1 :(得分:0)

我认为本文的解释更加清晰。 enter image description here

由于const全局变量具有内部链接,因此每个.cpp文件都会获得链接器看不到的全局变量的独立版本。在大多数情况下,因为它们是const,所以编译器会简单地优化变量。
术语“优化”是指编译器通过以不影响程序输出的方式删除内容来优化程序性能的任何过程。例如,假设您有一些常量变量x初始化为值4。无论您的代码引用变量x为何,编译器都可以将x替换为4(因为x是const,我们知道它永远不会更改为其他值) ),避免完全创建和初始化变量。

因此,“ cint”和“ scint”都是内部链接变量。

在C ++ 17之后定义全局变量的最佳实践:

inline constexpr double pi = 0;

工作机制:

C ++ 17引入了称为内联变量的新概念。在C ++中,术语“内联”已演变为“允许多个定义”。因此,内联变量是一个允许在多个文件中定义而不违反一个定义规则的变量。内联全局变量默认具有外部链接。

内联变量有两个必须遵守的主要限制: 1)内联变量的所有定义必须相同(否则,将导致未定义的行为)。 2)内联变量定义(不是前向声明)必须存在于使用该变量的任何文件中。

编译器会将所有内联定义合并为一个变量定义。这使我们能够在头文件中定义变量,并将其视为.cpp文件中某处只有一个定义。这些变量在包含它们的所有文件中也保持其可解释性。