在头文件中使用constexpr

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暗示constconst全局/命名空间范围暗示static(内部链接),这意味着包含此标题的每个翻译单元都有自己的副本PI.只有在获取地址或引用时才会分配该静态的内存,并且每个转换单元中的地址将不同.

这暗示static对于const变量是专门介绍了使用const代替#define在头文件中的C++来定义常量.如果没有static就不会有多个符号定义,如果该头文件包含在其中是连在一起的多个翻译单元连接错误.

在C++ 17中你也可以创建它inline,因此只有PI一个地址或引用的副本(即不是static).inline在C++ 17中引入了变量,以允许头文件中具有非const变量定义的仅头文件库.constexpr在静态数据成员暗示inline,所以inline没有必要.

换句话说,constexpr如果可能,您应该在头文件中使用常量,否则const.如果你要求该常量的地址在任何地方标记为相同inline.

  • 当它不是“内联”时会出现 ODR 问题吗? (3认同)
  • @codekaizer不,因为`静态`. (2认同)

Kev*_*inZ 6

C++17你很清楚.在C++11,您可以将其包装在一个函数中:

constexpr double PI () { return 3.14; }
Run Code Online (Sandbox Code Playgroud)

  • 请注意,在没有“inline”的 C++ 中,“constexpr”仍然会生成多个地址并占用多个内存位置,这并不理想,这可以通过修改我提供的示例来轻松测试以删除“inline”:https://stackoverflow.com /a/57399173/895245 (2认同)

Cir*_*四事件 6

C++17inline变量可运行示例

在以下位置提到了 C++17 内联变量:在头文件中使用 constexpr,这是一个最小的可运行示例,它显示仅使用单个内存位置:

主程序

#include <cassert>

#include "notmain.hpp"

int main() {
    // Both files see the same memory address.
    assert(&notmain_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 &notmain_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)

GitHub 上游.

C++ 标准保证地址是相同的。C++17 N4659 标准草案 10.1.6“内联说明符”:

6 具有外部链接的内联函数或变量在所有翻译单元中应具有相同的地址。

cppreference https://en.cppreference.com/w/cpp/language/inline解释说如果static没有给出,那么它有外部链接。

另请参阅:如何声明 constexpr extern?

在 GCC 7.4.0、Ubuntu 18.04 中测试。

C++20 std::math::pi

请注意,对于 Pi 的特定情况,C++20 提供了一个专用的变量模板,如下所示:How to use the PI constant in C++