188

ptrnamepnamernamecrnameおよびのプライベート メンバを持つクラスがあるとしageます。自分で初期化しないとどうなりますか? 次に例を示します。

class Example {
    private:
        int *ptr;
        string name;
        string *pname;
        string &rname;
        const string &crname;
        int age;

    public:
        Example() {}
};

そして、私は:

int main() {
    Example ex;
}

メンバーはexでどのように初期化されますか? ポインターはどうなりますか? デフォルトのコンストラクターと?stringで0 で初期化されます。参考メンバーは?また、const参照はどうですか?intstring()int()

より良い(バグのない)プログラムを書くことができるように、それを学びたいです。どんなフィードバックでも役に立ちます!

4

8 に答える 8

248

明示的な初期化の代わりに、クラス内のメンバーの初期化は、関数内のローカル変数の初期化と同じように機能します。

objectsの場合、デフォルトのコンストラクターが呼び出されます。たとえば、std::stringの場合、既定のコンストラクターはそれを空の文字列に設定します。オブジェクトのクラスにデフォルトのコンストラクターがない場合、明示的に初期化しないとコンパイル エラーになります。

プリミティブ型(ポインター、int など) の場合、それらは初期化されません。以前にそのメモリ位置にあった任意のジャンクが含まれています。

参照(例: std::string&) の場合、それらを初期化しないことは違法あり、コンパイラはエラーを出し、そのようなコードのコンパイルを拒否します。参照は常に初期化する必要があります。

したがって、特定のケースで、明示的に初期化されていない場合:

    int *ptr;  // Contains junk
    string name;  // Empty string
    string *pname;  // Contains junk
    string &rname;  // Compile error
    const string &crname;  // Compile error
    int age;  // Contains junk
于 2010-06-27T13:29:41.293 に答える
30

まず、mem-initializer-listとは何かを説明します。mem-initializer-listは、 mem-initializer のカンマ区切りのリストです。各mem-initializerは、メンバー名の後に が(続き、その後にexpression-listが続き、その後に). 式リストは、メンバーの構築方法です。たとえば、

static const char s_str[] = "bodacydo";
class Example
{
private:
    int *ptr;
    string name;
    string *pname;
    string &rname;
    const string &crname;
    int age;

public:
    Example()
        : name(s_str, s_str + 8), rname(name), crname(name), age(-4)
    {
    }
};

ユーザー提供の引数なしコンストラクターのmem-initializer-listname(s_str, s_str + 8), rname(name), crname(name), age(-4)は です。このmem-initializer-listは、nameメンバーが2 つの入力反復子を受け取るコンストラクターによって初期化されstd::stringrnameメンバーが への参照で初期化されnamecrnameメンバーが への const 参照で初期化されname、メンバーがage値で初期化されることを意味します-4

各コンストラクターには独自のmem-initializer-listがあり、メンバーは規定の順序 (基本的にはメンバーがクラスで宣言されている順序) でのみ初期化できます。したがって、 のメンバーは、、、、、およびExampleの順序でのみ初期化できます。ptrnamepnamernamecrnameage

メンバーのmem-initializerを指定しない場合、C++ 標準は次のように述べています。

エンティティがクラス型 ... の非静的データ メンバである場合、エンティティはデフォルトで初期化されます (8.5)。... それ以外の場合、エンティティは初期化されません。

ここで、 はクラス型の非静的データ メンバーであるため、 mem-initializer-list で初期化子が指定されてnameいない場合は、デフォルトで初期化されます。の他のすべてのメンバーはクラス型を持たないため、初期化されません。nameExample

標準で初期化されていないと記載されている場合、これは、任意の値を持つことができることを意味します。したがって、上記のコードは初期化pnameされていないため、何でもかまいません。

参照は常に初期化する必要があるというルールなど、他のルールに従う必要があることに注意してください。参照を初期化しないのはコンパイラ エラーです。

于 2010-06-27T14:07:48.807 に答える
10

クラスがスタック上でインスタンス化されている例の場合、初期化されていないスカラー メンバーの内容はランダムで未定義です。

グローバル インスタンスの場合、初期化されていないスカラー メンバーはゼロになります。

それ自体がクラスのインスタンスであるメンバーの場合、デフォルトのコンストラクターが呼び出されるため、文字列オブジェクトが初期化されます。

  • int *ptr;//初期化されていないポインター (またはグローバルの場合はゼロ)
  • string name;//コンストラクターが呼び出され、空の文字列で初期化されます
  • string *pname;//初期化されていないポインター (またはグローバルの場合はゼロ)
  • string &rname;//初期化に失敗するとコンパイルエラー
  • const string &crname;//初期化に失敗するとコンパイルエラー
  • int age;//スカラー値、初期化されていないランダム (またはグローバルの場合はゼロ)
于 2010-06-27T13:24:27.527 に答える
5

初期化されていない非静的メンバーには、ランダム データが含まれます。実際には、それらは割り当てられたメモリ位置の値を持つだけです。

もちろん、オブジェクトのパラメーター ( などstring) の場合、オブジェクトのコンストラクターはデフォルトの初期化を行うことができます。

あなたの例では:

int *ptr; // will point to a random memory location
string name; // empty string (due to string's default costructor)
string *pname; // will point to a random memory location
string &rname; // it would't compile
const string &crname; // it would't compile
int age; // random value
于 2010-06-27T13:28:12.697 に答える
2

コンストラクターを持つメンバーには、初期化のために呼び出されるデフォルトのコンストラクターがあります。

他の型の内容に依存することはできません。

于 2010-06-27T13:28:58.283 に答える
0

スタック上にある場合、独自のコンストラクターを持たない初期化されていないメンバーの内容はランダムで未定義になります。たとえそれがグローバルであっても、それらがゼロになることに依存するのは悪い考えです. スタック上にあるかどうかに関係なく、メンバーに独自のコンストラクターがある場合は、それが呼び出されて初期化されます。

したがって、string* pname がある場合、ポインターにはランダムなジャンクが含まれます。ただし、文字列名の場合、文字列のデフォルトのコンストラクターが呼び出され、空の文字列が返されます。参照型変数についてはわかりませんが、おそらくメモリのランダムなチャンクへの参照になるでしょう。

于 2010-06-27T13:32:50.653 に答える