ヘッダーファイルにこのような定義を含めることができますか?
constexpr double PI=3.14;
これをいくつかのcppファイルに含まれるヘッダーファイルに含めることに問題はありますか?
標準では、このconstexprには独自のメモリがあり、ヘッダーに追加し、いくつかのcppファイルにヘッダーを追加すると標準で述べているので、メモリ内の同じ値の複数のコピーとその他の厄介な問題を生成するのではないかと心配しています。
私はC++ 11を使用しています
constexpr
はconst
を意味し、グローバル/ネームスペーススコープのconst
はstatic
(内部リンケージ)を意味します。つまり、このヘッダーを含むすべての翻訳単位はPI
。その静的のメモリは、アドレスまたはそれへの参照が取得され、アドレスが各変換単位で異なる場合にのみ割り当てられます。
static
変数のconst
変数は、C++のヘッダーファイルで#define
の代わりにconst
を使用して定数を定義するために導入されました。 static
がなければ、リンクされた複数の翻訳単位にヘッダーファイルが含まれている場合、複数のシンボル定義リンカーエラーが発生します。
C++ 17では、inline
にすることもできます。そのため、アドレスまたは参照が取得された場合(つまり、PI
ではない)static
のコピーは1つだけです。 inline
変数はC++ 17で導入され、ヘッダーファイルに非const変数定義を持つヘッダーのみのライブラリを許可します。静的データメンバーのconstexpr
はinline
を意味するため、inline
は不要です。
つまり、可能であれば、ヘッダーファイルの定数にconstexpr
を使用する必要があり、そうでない場合はconst
を使用する必要があります。また、その定数のアドレスをどこでも同じにする必要がある場合は、inline
としてマークします。
C++17
あなたは明確です。 C++11
、それを関数でラップすることができます:
constexpr double PI () { return 3.14; }
C++ 17 inline
変数実行可能例
C++ 17インライン変数は、次の場所で言及されました: ヘッダーファイルでのconstexprの使用 これは、単一のメモリロケーションのみが使用されることを示す最小限の実行可能な例です。
main.cpp
#include <cassert>
#include "notmain.hpp"
int main() {
// Both files see the same memory address.
assert(¬main_i == notmain_func());
assert(notmain_i == 42);
}
notmain.hpp
#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP
inline constexpr int notmain_i = 42;
const int* notmain_func();
#endif
notmain.cpp
#include "notmain.hpp"
const int* notmain_func() {
return ¬main_i;
}
コンパイルして実行します:
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
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は次のように専用の変数テンプレートを提供します。 C++でPI定数を使用する方法