質問

このエラーが発生しています

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

実装は関数実装を最初に呼び出すだけなので、私のコードはそのようです。呼び出しごとにAccess変数が更新されるため、あまり意味をなさないため、静的になります。

Accessを静的に動作させても、他のすべての呼び出しでAccessが更新されるため、静的にしたくない。静的にせずに問題を回避する方法はありますか。

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

役に立ちましたか?

解決

次のように 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 と呼ばれます:ローカルに割り当てられたオブジェクトのコンストラクターとデストラクターにいくつかの便利なアクションを関連付けます。

他のヒント

@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のコメント:

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

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

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


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

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

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

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

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

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

static MyStruct Access = Implementation(this_b);

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top