4

私は C++11 の POD について調べてきましたが、私が読んだいくつかの場所では、静的初期化をサポートする POD について何か述べています。例えば:

StackOverflow について:

POD の考え方は、基本的に 2 つの異なるプロパティをキャプチャすることです
。1.静的初期化をサポートし
2. C++ で POD をコンパイルすると、C でコンパイルされた構造体と同じメモリ レイアウトが得られます。

(太字部分のみ関係あり)

ウィキペディアで

自明な型は静的に初期化できます。

どうやら私は静的初期化とは何かを理解していません。グローバル変数の作成は静的初期化の例だと思っていましたが、次のことはできますがFoo、POD ではありません。

#include <type_traits>
#include <iostream>

struct Foo {
  Foo() : x(0), y(0) {}
  int x;
  int y;
};

struct Bar {
  Bar() = default;
  int x;
  int y;
};

// Apparently the following two lines are not "static initialization" because
// Foo is non-POD yet we can still do this:
Foo f;
Bar b;

int main()
{
    if (std::is_pod<Foo>::value) std::cout << "Foo is a POD" << std::endl;
    else                         std::cout << "Foo is *not* a POD" << std::endl;

    if (std::is_pod<Bar>::value) std::cout << "Bar is a POD" << std::endl;
    else                         std::cout << "Bar is *not* a POD" << std::endl;
}

出力:

Foo is *not* a POD
Bar is a POD

では、静的初期化とは正確には何であり、自明なクラスとどのように関係しているのでしょうか? 例は素晴らしいでしょう。

4

4 に答える 4

5

静的期間を持つオブジェクトの初期化は、静的初期化と動的初期化の 2 つのパスに分けられます (静的という用語の乱用に注意してください:))。

動的初期化とは、関数の呼び出しを伴う初期化を指すため、実行可能ファイル自体に格納してロードするだけのリテラルからの初期化と比較して、実行時に行う必要があります。

于 2013-02-26T16:48:06.780 に答える
5

静的初期化は、静的ストレージ期間またはスレッド ストレージ期間を持つ変数に適用されます。これは 2 つのフェーズで発生します。

まず、静的ストレージ期間を持つ変数は、他の初期化の前にゼロで初期化されます。

次に定数の初期化を行います。定数の初期化は、次の 3 つの可能性のいずれかでなければなりません (§3.6.2/2):

  • 静的またはスレッド保存期間を持つ参照の初期化子に現れる各完全式 (暗黙的な変換を含む) が定数式 (5.19) であり、参照が静的保存期間を持つオブジェクトを指定する左辺値または一時的な(12.2 を参照);

  • 静的またはスレッド ストレージ期間を持つオブジェクトがコンストラクター呼び出しによって初期化される場合、コンストラクターが constexpr コンストラクターである場合、すべてのコンストラクター引数が定数式 (変換を含む) である場合、および関数呼び出し置換 (7.1.5) の後、すべての場合非静的データ メンバーの mem-initializers および波括弧または等号初期化子のコンストラクター呼び出しと完全式は定数式です。

  • 静的またはスレッド ストレージ期間を持つオブジェクトがコンストラクター呼び出しによって初期化されず、その初期化子に現れるすべての完全式が定数式である場合。

その他の初期化 (グローバル変数であっても) は動的初期化です。ただし、コンパイラは、動的初期化を静的初期化であるかのように扱うことができます。ただし、そのようにしても、プログラムの外部から見える効果が変わらない限り、正しい値を見つけられると仮定します (その値が正しくない場合でも)。正式には定数式として認定されます)。

a の定義constant expressionは (残念ながら) かなり長く複雑です。定義の基本的なスタイルは、 a を例外のリストに適合するものを除いて任意の式として定義するcore constant expressionことです (残念ながら、これは 1 ページを超える長さなので、すばやく簡単に理解できるものに要約するのは簡単ではありません)。

于 2013-02-26T16:53:14.600 に答える
4

静的初期化とは、コンパイル時の値を使用して変数を初期化することで、値が最終的に実行可能イメージに「焼き付けられる」ようにします (コードを実際に実行する必要はありません)。

struct Foo {
  int x;
  int y;
};

Foo foo = { 0, 1 };

上記の例struct Fooでは POD であるため、コンパイラは、そのメモリ レイアウトが 2 つの整数が隣り合っていることを認識しています。また、 をおよびにfoo.x初期化する必要があることも認識しています。これは、コンパイル時にどのように見えるべきかの「メモリ イメージ」を生成し、それを実行可能イメージに書き込むのに十分な情報です。0foo.y1foo

イメージが後で実行されると、OS ローダーはその内容をメモリ アドレスにマップし、この方法でfoo「有効」にします。foo重要なことは、プロセス (コードと、最初に実行される C/C++ ランタイムからのコードを含む) が単一の CPU 命令を実行する時間さえも持つ前に、 の「初期化」が実際に完了していることです。

于 2013-02-26T16:45:29.527 に答える
-1

静的メンバーの初期化は、クラス スコープで発生します。したがって、他のメンバー データまたは関数にアクセスできます。

それはMSDNから引用されています

それがそこでどのように機能するかの良い例があります。

于 2013-02-26T16:49:37.147 に答える