2

質問を詳しく読むのが面倒な人のために、質問は太字になっています。

これは、この質問のフォローアップです。これは、関数内の静的変数の初期化セマンティクスに関係しています。静的変数は一度初期化する必要があり、それらの内部状態は後で変更される可能性があります-私が(現在)リンクされた質問で行っているように。ただし、問題のコードでは、後で変数の状態を変更する機能は必要ありません。

文字列オブジェクトの内部状態を変更する必要がないため、私の立場を明確にさせてください。このコードは、メタ プログラミング用の特性クラス用であり、const char * const ptr の恩恵を受けるため、理想的にはローカル コストの static const 変数が必要です。私の経験に基づいた推測では、この場合、問題の文字列はリンクローダーによってメモリに最適に配置され、コードはより安全になり、意図したセマンティクスにマップされます。

これは、そのような変数のセマンティクスにつながります。「C++ プログラミング言語第 3 版 -- Stroustrup」には、この問題について (私が見つけた限りでは) 何も言うことがありません。つまり、変数は、スレッドの制御フローが最初にコードに到達したときに 1 回初期化されるということだけです。これにより、次のコードが適切かどうか、またそうでない場合、意図されたセマンティクスは何かを考えるようになります。

#include <iostream>
const char * const GetString(const char * x_in)
{
    static const char * const x = x_in;
    return x;
}

int main()
{
  const char * const temp = GetString("yahoo");
  std::cout << temp << std::endl;
  const char * const temp2 = GetString("yahoo2");
  std::cout << temp2 << std::endl;
}

以下は GCC でコンパイルし、「yahoo」を 2 回出力します。これが私が望むものです-しかし、それは標準に準拠していない可能性があります(これが私がこの質問を投稿する理由です)。"SetString" と "String" の 2 つの関数を使用して、後者が最初の関数に転送されるようにする方がエレガントな場合があります。標準に準拠している場合、誰かがブースト(または他の場所)でのテンプレートの実装を知っていますか?

編集: 2010 年 5 月 11 日

次のマクロを使用して、コンパイル時の情報をエンコードするクラスで上記のゲッター/セッターを生成しています。

#define MACRO_STATIC_SETTING_PTR(name, type)                          \
  static const type const set_##name (const type const name##_in) {   \
    static const type const name = name##_in;                         \
    return name;                                                      \
  }                                                                   \
  static const type const name() {                                    \
    return set_##name(NULL);                                          \
  } 

#define MACRO_STATIC_SETTING(name, type)                              \
  static const type set_##name (const type name##_in) {               \
    static const type name = name##_in;                               \
    return name;                                                      \
  }                                                                   \
  static const type name() {                                          \
    return set_##name(NULL);                                          \
  } 

これらのマクロは、クラス宣言内に配置されます。例えば:

template<class tag>
class ConfigInstance{
public:
  MACRO_STATIC_SETTING_PTR(sqllite3_filename, char *)
};

うまくいけば、これは他の人に役立つでしょう。

4

1 に答える 1

4

C++ 標準のパート 6.7 §4 (宣言ステートメント) を見てみましょう。

実装は、実装が名前空間スコープで静的ストレージ期間を持つオブジェクトを静的に初期化することを許可されているのと同じ条件下で、静的ストレージ期間を持つ他のローカル オブジェクトの早期初期化を実行することが許可されています。それ以外の場合、そのようなオブジェクトは、コントロールが最初に宣言を通過するときに初期化されます。このようなオブジェクトは、初期化の完了時に初期化されたと見なされます。

したがって、次の 2 つのケースがあります。

  1. static local を使用して関数に入る前にx、どのような値xが得られるか。その後、コンパイラはできるだけ早く (コンパイル時でも) 値を初期化できます。
  2. x初期化の値は、最初に関数に入ったときだけではありません。

そうです、gcc が行うことは、あなたが望むだけでなく、この動作も標準に準拠しています。

于 2010-05-10T20:52:35.577 に答える