9

次の作業コードがあります。

#include <string>
#include <iostream>

class A {
public:
  const std::string test = "42";
  //static const std::string test = "42"; // fails
};

int main(void){
  A a;
  std::cout << a.test << '\n';
}

テストをaにすることができない正当な理由はありstatic constますか? C++ 11より前は、標準によって制約されていたことを理解しています。私は、c++11 がクラス内初期化を導入して、少し使いやすくしたと考えました。私もかなり前から、そのようなセマンティックは整数型に使用できません。

もちろん、次の形式のクラス外初期化で機能しますconst std::string A::test = "42";

非静的にすることができれば、問題は2つのうちの1つにあると思います。クラス外スコープで初期化します (通常const、オブジェクトのインスタンス化中に s が作成されます)。しかし、クラスの他のメンバーから独立したオブジェクトを作成している場合、これは問題ではないと思います。2 つ目は、静的メンバーに複数の定義があることです。たとえば、複数に含まれている場合.cppファイルがいくつかのオブジェクト ファイルに到達すると、リンカはそれらのオブジェクトを一緒にリンクするときに (たとえば、1 つの実行可能ファイルに)、同じシンボルのコピーが含まれるため、問題が発生します。私の理解では、これはヘッダーのクラス宣言のすぐ下にクラス外を提供し、この共通ヘッダーを複数の場所に含める状況とまったく同じです。私が思い出したように、これはリンカーエラーにつながります。

ただし、これを処理する責任はユーザー/プログラマーに移されました。ライブラリにstaticクラス外の定義を提供する必要がある場合は、それを別のオブジェクト ファイルにコンパイルしてから、他のすべてのオブジェクトをこのファイルにリンクする必要があります。シンボル。

クラス定義内で初期化されている場合でも、静的メンバーを個別に定義する必要がありますか?の回答を読みました。クラスで非 const 静的メンバーまたは静的配列を初期化できないのはなぜですか? .

私はまだ知りたいです:

  1. それは単なる標準的なものですか、それとももっと深い理由がありますか?
  2. constexprこれは、およびユーザー定義のリテラル メカニズムで回避できますか。clang と g++ はどちらも、変数に非リテラル型を含めることはできないと言っています。多分私はそれを作ることができます。(たぶん、何らかの理由でそれも悪い考えです)
  3. リンカーがシンボルのコピーを 1 つだけ含めることは、本当に大きな問題なのでしょうか? それはstatic constすべて、バイナリの正確な不変のコピーである必要があるためです。

私が何かを見逃したり誤解したりする場合は、コメントしてください。

4

1 に答える 1

7

あなたの質問には2つの部分があります。基準は何と言っていますか?そして、それはなぜですか?

type の static メンバーのconst std::string場合、クラス指定子の外で定義し、翻訳単位の 1 つに 1 つの定義を含める必要があります。これは One Definition Rule の一部であり、C++ 標準の第 3 節で指定されています。

しかし、なぜ?

問題は、静的ストレージ期間を持つオブジェクトは、最終的なプログラム イメージで一意の静的ストレージを必要とするため、1 つの特定の翻訳単位からリンクする必要があることです。クラス指定子は、1 つの翻訳単位にホームを持たず、型を定義するだけです (それが使用されるすべての翻訳単位で同じように定義する必要があります)。

定数積分がストレージを必要としない理由は、コンパイラによって定数式として使用され、使用時にインライン化されるためです。プログラムイメージには決してなりません。

ただし、 のような複合型はstd::string、たとえconst. これは、動的に初期化する必要がある場合があるためです (メインへのエントリの前にコンストラクターを呼び出す必要があります)。

コンパイラーはオブジェクトに関する情報を、それらが使用される各翻訳単位に静的ストレージ期間で格納する必要があり、リンカーはリンク時にこれらの定義をプログラム イメージ内の 1 つのオブジェクトにマージする必要があると主張することができます。これが行われない理由についての私の推測は、リンカーからのインテリジェンスが多すぎることです。

于 2013-06-27T21:12:02.067 に答える