1

このエラーが発生します

error: Access.Core may be used uninitialized in this function

そしてこれは私のコードです:

 static int FirstTime = 1;
 MyStruct Access;

 if (FirstTime) {
   FirstTime = 0;
   Access = Implementation();
   DoSomething(Access);
 }

 if(Other_Variable) {
    Access = Implementation2();
    DoSomething(Access);
  }

  //The Other_Variable will be set to 1 and to 0 by other part of the code

初めて関数Implementationを呼び出したいので、私のコードはそのようなものです。すべての呼び出しでAccess変数が更新されるため、静的にすることはあまり意味がありません。

Accessを静的に機能させるが、他のすべての呼び出しでAccessが更新されるため、静的にするのは好きではありません。問題を静的にせずに回避する方法はありますか?

また、静的変数を使用する代わりに、関数を1回だけ実行するためのより良いオプションを歓迎します。

4

4 に答える 4

6

このAccessように作成します(そして削除FirstTimeしますif):

static MyStruct Access = Implementation(this_b);

この警告が表示される理由は、静的変数が1回の関数呼び出しで存続するためです。それらの値は、すべての関数呼び出しにわたって保持されます(どのスレッドがその関数を呼び出すかに関係なく)。したがって、FirstTimeを初期化するかどうかを制御しますAccess。コードが含まれている関数を初めて呼び出すと、Access変数が正しく初期化されます。ただし、それ以降の関数呼び出しごとに、FirstTimeはゼロになり、初期化されなくAccessなるため、コードで初期化されていない変数が使用されます。

編集:ここで、更新された情報を使用して、2つの機能があると言いますImplementation。初めて使用する場合と、それ以外の場合は別の関数を使用する場合。では、これはどうですか?

 // static will be false/zero by default
 static bool AlreadyCalled;
 MyStruct Access;

 if (!AlreadyCalled) {
   Access = Implementation();
   AlreadyCalled = true;
 } else {
   Access = Implementation2();
 }

ただし、実際のユースケースによっては、これを処理するためのより良い方法がある場合があります。たとえば、次のAccessようにの状態を更新してみませんか。

// let the default constructor initialize it
// to a plausible state
static MyStruct Access;

// use RAII to update the state of Access when this
// function returns. 
MyUpdater updater(Access);

// now, do whatever the function does. 

このようなものMyUpdater

struct MyUpdater {
    MyStruct &s;
    MyUpdater(MyStruct &s):s(s) { }
    ~MyUpdater() {
        s.ChangeState();
    }
};

そのパターンは次のように呼ばれRAIIます。ローカルに割り当てられたオブジェクトのコンストラクタとデストラクタにいくつかの有用なアクションを関連付けます。

于 2009-03-09T23:28:45.583 に答える
2

@litbの答えは興味深いです。同等のプログラムが続きます。コードはC++で説明されているようにコンパイルおよび動作しますが、Cではコンパイルされません。

#include <stdio.h>

static int newval(void) { return 3; }

void inc(void)
{
    static int a = newval();

    a++;
    printf("%d\n", a);
}

int main(void)
{
    int i;
    for (i = 0; i < 10; i++)
        inc();
    return(0);
}

gccは言う:

xc:関数'inc'内:xc:7:エラー:初期化要素が定数ではありません

g++はそれに非常に満足しています。

これは、私が気付いていなかったCとC ++の違いです(ただし、これは300文字に収まらないため、コメントにするのは簡単ではありません)。


@Eduardoは、コメントの中で質問の1つを尋ねました。「なぜ、Cはこれを許可せず、C ++はそれを許可するのですか?」 答えは300文字以上なので...

@litbがコメントで述べたように、Cでは静的変数の初期化子にのみ定数を使用できます。これは、main()が呼び出される前に値が設定され、main()が呼び出される前にユーザー定義関数が呼び出されないためです。対照的に、C ++では、main()が呼び出される前に、グローバル変数と静的変数を(ユーザー定義の)コンストラクターで初期化できます。したがって、他のユーザー定義関数も呼び出せない理由はないため、初期化は妥当です。C89では、自動(ローカル)変数で使用できる初期化子に制限があります。C99では、ほとんどすべての式を使用して、任意のローカル変数を初期化できます。

于 2009-03-09T23:45:20.457 に答える
1

アクセスは静的ではないため、関数が呼び出されるたびに新しいインスタンスが作成されます。初めての場合にのみ、実際に値を割り当てます。この値は、関数が終了するとすぐに失われます。

関数の呼び出し間でAccessを永続化する必要がある場合は、静的にします。

于 2009-03-09T23:27:40.920 に答える
1

Access静的ではないため、すべての呼び出しで作成する必要があります。

コードを次のように単純化することを検討してください。

static MyStruct Access = Implementation(this_b);

これにより、メソッドが最初に実行されたときにのみ関数が呼び出され、Access呼び出しの間に値が保持されます。

于 2009-03-09T23:30:20.307 に答える