man*_*ans 20 c++ constexpr c++11
我可以在头文件中有这样的定义吗?
constexpr double PI=3.14;
Run Code Online (Sandbox Code Playgroud)
在包含在几个cpp文件中的头文件中有这个问题吗?
我担心,因为它在标准中说这个constexpr有自己的内存,把它放在头文件中,并在几个cpp文件中添加标题,在内存中生成相同值的多个副本以及其他一些令人讨厌的问题.
我正在使用C++ 11
Max*_*kin 37
constexpr
暗示const
和const
全局/命名空间范围暗示static
(内部链接),这意味着包含此标题的每个翻译单元都有自己的副本PI
.只有在获取地址或引用时才会分配该静态的内存,并且每个转换单元中的地址将不同.
这暗示static
对于const
变量是专门介绍了使用const
代替#define
在头文件中的C++来定义常量.如果没有static
就不会有多个符号定义,如果该头文件包含在其中是连在一起的多个翻译单元连接错误.
在C++ 17中你也可以创建它inline
,因此只有PI
一个地址或引用的副本(即不是static
).inline
在C++ 17中引入了变量,以允许头文件中具有非const变量定义的仅头文件库.constexpr
在静态数据成员暗示inline
,所以inline
没有必要.
换句话说,constexpr
如果可能,您应该在头文件中使用常量,否则const
.如果你要求该常量的地址在任何地方标记为相同inline
.
在C++17
你很清楚.在C++11
,您可以将其包装在一个函数中:
constexpr double PI () { return 3.14; }
Run Code Online (Sandbox Code Playgroud)
C++17inline
变量可运行示例
在以下位置提到了 C++17 内联变量:在头文件中使用 constexpr,这是一个最小的可运行示例,它显示仅使用单个内存位置:
主程序
#include <cassert>
#include "notmain.hpp"
int main() {
// Both files see the same memory address.
assert(¬main_i == notmain_func());
assert(notmain_i == 42);
}
Run Code Online (Sandbox Code Playgroud)
不是main.hpp
#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP
inline constexpr int notmain_i = 42;
const int* notmain_func();
#endif
Run Code Online (Sandbox Code Playgroud)
notmain.cpp
#include "notmain.hpp"
const int* notmain_func() {
return ¬main_i;
}
Run Code Online (Sandbox Code Playgroud)
编译并运行:
g++ -c -o notmain.o -std=c++17 -Wall -Wextra -pedantic notmain.cpp
g++ -c -o main.o -std=c++17 -Wall -Wextra -pedantic main.cpp
g++ -o main -std=c++17 -Wall -Wextra -pedantic main.o notmain.o
./main
Run Code Online (Sandbox Code Playgroud)
C++ 标准保证地址是相同的。C++17 N4659 标准草案 10.1.6“内联说明符”:
6 具有外部链接的内联函数或变量在所有翻译单元中应具有相同的地址。
cppreference https://en.cppreference.com/w/cpp/language/inline解释说如果static
没有给出,那么它有外部链接。
在 GCC 7.4.0、Ubuntu 18.04 中测试。
C++20 std::math::pi
请注意,对于 Pi 的特定情况,C++20 提供了一个专用的变量模板,如下所示:How to use the PI constant in C++