0

古いコードを c++98 から c++14 にリファクタリングしようとしています。また、古い gcc (c++98) と新しい gcc (c++14) の両方でコンパイルする必要があります。これは、古いコードがどのように見えるかです (これは、複雑なコードの完全に構成された例です。このクラスの static const は、別のクラスで使用されます)。

// BankAccount.h
namespace bank {
class BankAccount {
 public:
    static const unsigned int account_number = 123456789;
    static const double balance = 0.0;
    BankAccount();
    ....
};
}

// BankAccount.cpp
namespace bank {
    BankAccount::BankAccount() {}
    ....
}

C++ 11 からは int と enum のみがクラス宣言でのみ初期化できるようです。

質問: 上記のようにクラス宣言内で静的 const 変数を初期化することにより、静的初期化順序の大失敗を回避できますか? 上記のコードでは、この静的な初期化順序の問題は見られませんでした。静的な double と float を .cpp ファイルに移動した場合、問題について心配する必要がありますか?

4

1 に答える 1

1

(更新: 質問がstatic constメンバーに変更されたため)

それらを宣言することによりstatic const、整数変数に対して安全です。最新の C++ では、それらを として宣言することに違いはありませんstatic constexpr。初期化されていない (またはゼロで初期化された) 数値へのアクセスの問題に遭遇しないことが、言語によって保証されています。

double のような浮動小数点の場合、 を使用しない限りコンパイルされませんconstexpr。ただし、これは C++98 では使用できない機能です。がないconstexprと、次のようなコンパイル エラーが発生します。

// gcc
example.cpp:6:25: error: ‘constexpr’ needed for in-class initialization of static data member ‘const double bank::BankAccount::balance’ of non-integral type [-fpermissive]
    6 |     static const double balance = 0.0;
      |                         ^~~~~~~

または非標準機能のみ:

// clang with -Wall -std=c++98
example.cpp:6:25: warning: in-class initializer for static data member of type 'const double' is a GNU extension [-Wgnu-static-float-init]
    static const double balance = 0.0;

(それらを宣言せずに古い回答constですが、それらを非定数にします)

例についてよろしいですか?私はそれがコンパイルされるとは思わない (C++98 と最新の C++ の両方で)。初期化をクラス定義の外に移動しない限り、次のような結果が得られます。

// gcc
example.cpp:5:30: error: ISO C++ forbids in-class initialization of non-const static member ‘bank::BankAccount::account_number’
    5 |     static unsigned long int account_number = 123456789;
      |                              ^~~~~~~~~~~~~~
example.cpp:6:19: error: ‘constexpr’ needed for in-class initialization of static data member ‘double bank::BankAccount::balance’ of non-integral type [-fpermissive]
    6 |     static double balance = 0.0;
      |                   ^~~~~~~
// clang
example.cpp:5:30: error: non-const static data member must be initialized out of line
    static unsigned long int account_number = 123456789;
                             ^                ~~~~~~~~~
example.cpp:6:19: error: non-const static data member must be initialized out of line
    static double balance = 0.0;
                  ^         ~~~

移動すると、静的初期化順序の大失敗に終わる可能性があります。値はゼロ初期化として開始され、実際の初期化コードがいつ実行されるかはリンカーによって異なります。

ただし、変数を定数として宣言できれば安全です。

于 2021-04-24T12:38:28.647 に答える