258

このキーワードstaticは、C++ でいくつかの意味を持つもので、非常に紛らわしく、実際にどのように機能するかについて頭を悩ませることはできません。

私が理解していることからstatic、保存期間があります。つまり、グローバルの場合はプログラムの存続期間中持続しますが、ローカルについて話している場合は、デフォルトでゼロ初期化されていることを意味します。

C++ 標準は、キーワードを持つクラス データ メンバーに対して次のように述べていますstatic

3.7.1 静的保存期間 [basic.stc.static]

3 キーワード static を使用して、静的ストレージ期間を持つローカル変数を宣言できます。

4 クラス定義でクラス データ メンバーに適用される static キーワードは、データ メンバーに静的ストレージ期間を与えます。

local variableとはどういう意味ですか? それは関数のローカル変数ですか?関数 local を宣言するstaticと、最初にこの関数に入ったときに一度だけ初期化されることもあるためです。

また、クラスメンバーに関する保存期間についてのみ説明していますが、インスタンス固有ではないことについてはどうですか?それもstaticnoのプロパティですか? それとも保存期間ですか?

staticでは、ファイル スコープの場合はどうでしょうか。すべてのグローバル変数は、デフォルトで静的ストレージ期間を持つと見なされますか? 以下 (セクション 3.7.1 から) はそのことを示しているようです:

1 動的ストレージ期間を持たず、スレッドストレージ期間を持たず、ローカルではないすべての変数は、静的ストレージ期間を持ちます。これらのエンティティのストレージは、プログラムの期間中持続するものとします (3.6.2、3.6.3)

static変数のリンケージとどのように関連していますか?

このキーワード全体staticは実に紛らわしいです。誰かが英語のさまざまな用途を明確にし、クラスメンバーをいつ初期化するか教えてもらえますか?static

4

9 に答える 9

12

ファイル スコープで変数を宣言すると、その変数はそのstatic特定のファイルでのみ使用できます (技術的には *translation ユニットですが、これをあまり複雑にしないでください)。例えば:

a.cpp

static int x = 7;

void printax()
{
    cout << "from a.cpp: x=" << x << endl;
}

b.cpp

static int x = 9;

void printbx()
{
    cout << "from b.cpp: x=" << x << endl;
}

main.cpp:

int main(int, char **)
{
    printax(); // Will print 7
    printbx(); // Will print 9

    return 0;
}

ローカル変数の場合static、変数はゼロで初期化され、呼び出し間でその値を保持することを意味します。

unsigned int powersoftwo()
{
    static unsigned lastpow;

    if(lastpow == 0)
        lastpow = 1;
    else
        lastpow *= 2;

    return lastpow;
}

int main(int, char **)
{
    for(int i = 0; i != 10; i++)
        cout << "2^" << i << " = " << powersoftwo() << endl;
}

クラス変数の場合、そのクラスのすべてのメンバー間で共有される変数のインスタンスが 1 つしかないことを意味します。権限によっては、完全修飾名を使用してクラスの外部から変数にアクセスできます。

class Test
{
private:
    static char *xxx;

public:
    static int yyy;

public:
    Test()
    {        
        cout << this << "The static class variable xxx is at address "
             << static_cast<void *>(xxx) << endl;
        cout << this << "The static class variable yyy is at address "
             << static_cast<void *>(&y) << endl;
    }
};

// Necessary for static class variables.
char *Test::xxx = "I'm Triple X!";
int Test::yyy = 0;

int main(int, char **)
{
    Test t1;
    Test t2;

    Test::yyy = 666;

    Test t3;
};

非クラス関数を としてマークするとstatic、その関数はそのファイルからのみアクセス可能になり、他のファイルからはアクセスできなくなります。

a.cpp

static void printfilename()
{ // this is the printfilename from a.cpp - 
  // it can't be accessed from any other file
    cout << "this is a.cpp" << endl;
}

b.cpp

static void printfilename()
{ // this is the printfilename from b.cpp - 
  // it can't be accessed from any other file
    cout << "this is b.cpp" << endl;
}

クラス メンバー関数の場合、関数をオブジェクトの特定のインスタンスで呼び出す必要がないことを意味するものとしてマークする(つまり、ポインターstaticを持たない)。this

class Test
{
private:
    static int count;

public:
    static int GetTestCount()
    {
        return count;
    };

    Test()
    {
        cout << this << "Created an instance of Test" << endl;
        count++;
    }

    ~Test()
    {
        cout << this << "Destroyed an instance of Test" << endl;
        count--;
    }
};

int Test::count = 0;

int main(int, char **)
{
    Test *arr[10] = { NULL };

    for(int i = 0; i != 10; i++)
        arr[i] = new Test();

    cout << "There are " << Test::GetTestCount() << " instances of the Test class!" << endl;

    // now, delete them all except the first and last!
    for(int i = 1; i != 9; i++)
        delete arr[i];        

    cout << "There are " << Test::GetTestCount() << " instances of the Test class!" << endl;

    delete arr[0];

    cout << "There are " << Test::GetTestCount() << " instances of the Test class!" << endl;

    delete arr[9];

    cout << "There are " << Test::GetTestCount() << " instances of the Test class!" << endl;

    return 0;
}
于 2013-03-05T23:04:58.170 に答える
8

静的変数は、各クラスが独自の変数を持つのではなく、クラスのすべてのインスタンス間で共有されます。

class MyClass
{
    public:
    int myVar; 
    static int myStaticVar;
};

//Static member variables must be initialized. Unless you're using C++11, or it's an integer type,
//they have to be defined and initialized outside of the class like this:
MyClass::myStaticVar = 0;

MyClass classA;
MyClass classB;

「MyClass」の各インスタンスには独自の「myVar」がありますが、同じ「myStaticVar」を共有します。実際、「myStaticVar」にアクセスするために MyClass のインスタンスさえ必要なく、次のようにクラスの外部にアクセスできます。

MyClass::myStaticVar //Assuming it's publicly accessible.

関数内でローカル変数として (クラス メンバー変数としてではなく) 使用すると、static キーワードは別のことを行います。これにより、グローバル スコープを指定せずに永続変数を作成できます。

int myFunc()
{
   int myVar = 0; //Each time the code reaches here, a new variable called 'myVar' is initialized.
   myVar++;

   //Given the above code, this will *always* print '1'.
   std::cout << myVar << std::endl;

   //The first time the code reaches here, 'myStaticVar' is initialized. But ONLY the first time.
   static int myStaticVar = 0;

   //Each time the code reaches here, myStaticVar is incremented.
   myStaticVar++;

   //This will print a continuously incrementing number,
   //each time the function is called. '1', '2', '3', etc...
   std::cout << myStaticVar << std::endl;
}

永続性の点ではグローバル変数ですが、スコープ/アクセシビリティではグローバルではありません。

静的メンバー関数を使用することもできます。静的関数は基本的に非メンバー関数ですが、クラス名の名前空間内にあり、クラスのメンバーへのプライベート アクセスがあります。

class MyClass
{
    public:
    int Func()
    {
        //...do something...
    }

    static int StaticFunc()
    {
        //...do something...
    }
};

int main()
{
   MyClass myClassA;
   myClassA.Func(); //Calls 'Func'.
   myClassA.StaticFunc(); //Calls 'StaticFunc'.

   MyClass::StaticFunc(); //Calls 'StaticFunc'.
   MyClass::Func(); //Error: You can't call a non-static member-function without a class instance!

   return 0;
}

メンバー関数を呼び出すと、関数を呼び出すクラスのインスタンスへのポインターである「this」と呼ばれる隠しパラメーターがあります。静的メンバー関数にはその隠しパラメーターはありません...クラスインスタンスなしで呼び出すことができますが、動作する「this」ポインターがないため、クラスの非静的メンバー変数にもアクセスできません。それらは特定のクラス インスタンスで呼び出されていません。

于 2013-03-05T22:42:51.453 に答える
1

ローカル変数とはどういう意味ですか? それは関数のローカル変数ですか?

はい - 関数ローカル変数などの非グローバル。

関数 local を static として宣言すると、最初にこの関数に入ったときに一度だけ初期化されることもあるためです。

右。

また、クラスメンバーに関する保存期間についてのみ説明していますが、インスタンス固有ではないことについてはどうですか?これは静的なプロパティでもありますか? それとも保存期間ですか?

class R { static int a; }; // << static lives for the duration of the program

つまり、Rshareのすべてのインスタンスint R::a--int R::aは決してコピーされません。

では、静的スコープとファイル スコープの場合はどうでしょうか。

事実上、必要に応じてコンストラクタ/デストラクタを持つグローバルです。初期化はアクセスするまで延期されません。

static は変数のリンケージとどのように関連していますか?

関数ローカルの場合、それは外部です。アクセス: 関数からアクセスできます (もちろん、返さない限り)。

クラスの場合、それは外部です。アクセス: 標準のアクセス指定子が適用されます (public、protected、private)。

static宣言されている場所 (ファイル/名前空間) に応じて、内部リンケージを指定することもできます。

この static キーワード全体が実に紛らわしい

C++ では目的が多すぎます。

誰かが英語のさまざまな用途を明確にし、静的クラスメンバーをいつ初期化するか教えてもらえますか?

mainロードされ、コンストラクターがある場合は、事前に自動的に初期化されます。それは良いことのように聞こえるかもしれませんが、初期化の順序はほとんど制御できないため、複雑な初期化を維持するのが非常に難しくなり、これを最小限に抑えたいと考えています。プロジェクト。静的な保存期間を持つデータに関しては、特に可変 (グローバル変数) の場合は、この設計を最小限に抑えるようにしてください。初期化の「時間」もさまざまな理由で異なります。ローダーとカーネルには、問題のデータに応じて、メモリフットプリントを最小限に抑え、初期化を遅らせるためのいくつかのトリックがあります。

于 2013-03-05T23:06:29.200 に答える