Domanda

Ricevo questo errore

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

E questo è il mio codice:

 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

Il mio codice è così perché voglio chiamare la funzione Implementazione solo la prima volta. In ogni chiamata la variabile Access verrà aggiornata, quindi non ha molto senso renderla statica.

Se accedo a Access statico funziona, ma non mi piace renderlo statico perché in ogni altra chiamata Access verrà aggiornato. Un modo per evitare il problema senza renderlo statico ?.

Anche le opzioni migliori da eseguire solo una volta invece di utilizzare una variabile statica sono benvenute.

È stato utile?

Soluzione

Rendi Accedi in questo modo (e rimuovi FirstTime e se ):

static MyStruct Access = Implementation(this_b);

Il motivo per cui viene visualizzato questo avviso è perché le variabili statiche sopravvivono a una chiamata di funzione. Il loro valore viene mantenuto per tutte le chiamate di funzione ( senza riguardo a quale thread chiama quella funzione). Pertanto, FirstTime controllerà se si inizializza Accesso . La prima volta che si chiama la funzione in cui si trova il codice, verrà inizializzata correttamente la variabile Access . Ma con ogni ulteriore chiamata di funzione, FirstTime è zero e non inizializzerai più Access e quindi utilizzerai una variabile non inizializzata nel codice .

Modifica: Ora, con le tue informazioni aggiornate, dici di avere due funzioni Implementazione . La prima volta che si desidera utilizzare uno e tutte le altre volte si desidera utilizzare un'altra funzione. Che ne dici allora:

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

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

A seconda del caso d'uso reale, tuttavia, potrebbero esserci modi migliori per gestirlo. Ad esempio, perché non aggiornare lo stato di Access , in questo modo:

// 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. 

Qualcosa del genere per MyUpdater :

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

Questo modello è chiamato RAII : associ alcune azioni utili al costruttore e al distruttore di un oggetto allocato localmente.

Altri suggerimenti

La risposta di @ litb è interessante. Segue un programma equivalente. Il codice viene compilato e funziona come indicato in C ++, ma non viene compilato in 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 dice:

x.c: nella funzione 'inc': x.c: 7: errore: l'elemento di inizializzazione non è costante

g ++ ne è abbastanza soddisfatto.

Questa è una differenza tra C e C ++ di cui non ero a conoscenza (ma questo non si adattava a 300 caratteri, quindi non posso farne un commento, facilmente).


@Eduardo ha posto una delle domande nei commenti: " Perché C non lo consente e C ++ lo consente? " ;. Poiché la risposta è più di 300 caratteri ...

Come diceva @litb nei commenti, in C puoi usare solo costanti per inizializzatori di variabili statiche. Ciò è in parte dovuto al fatto che i valori sono impostati prima della chiamata a main () e nessuna funzione definita dall'utente viene chiamata prima della chiamata a main (). Il C ++, al contrario, consente alle variabili globali e statiche di essere inizializzate dai costruttori (definiti dall'utente) prima che venga chiamato main (), quindi non c'è motivo di non consentire la chiamata anche ad altre funzioni definite dall'utente, quindi l'inizializzazione è ragionevole. Con C89, sei limitato agli inizializzatori che puoi usare con variabili automatiche (locali); in C99, puoi usare praticamente qualsiasi espressione per inizializzare qualsiasi variabile locale.

L'accesso non è statico, quindi viene creata una nuova istanza ogni volta che viene chiamata la funzione. Solo alla prima volta in realtà si assegna alcun valore ad esso; questo valore viene perso non appena la funzione esce.

Se hai bisogno di Access per persistere tra le chiamate alla funzione, rendila statica.

Accesso non è statico e pertanto deve essere creato in ogni chiamata.

Valuta di semplificare il codice in qualcosa del tipo:

static MyStruct Access = Implementation(this_b);

Ciò garantisce che la funzione venga chiamata solo la prima volta che viene eseguito il metodo e che Accesso conterrà il valore tra le chiamate.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top