2011-10-05 2 views
17

Sto cercando qualche aiuto nella prossima situazione:
ho un po 'di classe e qualche metodo in essa, la sintassi è simile a questo:Il corpo di inizializzazione dell'array come parametro di funzione (C-array), è possibile?

class SomeClass { 
    public: 
      void doSomething(int *a); 
}; 

quindi voglio chiamare questo metodo come

SomeClass::doSomething({ 0, 1, 2, 3, 4 }); 

È possibile in qualsiasi lingua? Qualsiasi implementazione (C++, C, obj-c, obj-C++) è benvenuta! So che questo blocco di inizializzazione è un corpo di array, come

int *a = { 0, 1, 2, 3, 4 }; 
SomeClass::doSomething(a); 

Ma interfaccia sarà grande, credo che, se non ci saranno variabili TEMP prima di chiamate di funzione (come non abbiamo bisogno di conoscere la tipo di parametro in class-client). Quindi, c'è qualche possibilità di farlo?

risposta

8

Si tratta di C++ 11 initializer lists (sezione 18.9).

void foo (std :: initializer_list <int> inputs) { 
    for (auto i : inputs) { 
     // ... 
    } 
} 

foo ({10, 20, 30}); 

Solo il compilatore può creare un elenco di inizializzazione, ma si può trattare come un container standard STL-stile con iteratori begin(), end(), size(), e ad accesso casuale.

std::vector (e mi aspetto che alcuni altri contenitori) può ora essere costruiti con le liste di inizializzazione, così

std :: vector <std :: string> foo {"a", "b"}; 

è equivalente a

std :: vector <std :: string> foo; 
foo .push_back ("a"); 
foo .push_back ("b"); 

eccezione del fatto che può svolgere un minor numero di allocazioni. Si noti che lo const char* è stato convertito automaticamente in std::string.

+0

In realtà, questo funzionerà con * qualsiasi * classe contenitore, grazie all'inizializzazione uniforme di C++ 11. –

20

In C99 funziona:

functionThatTakesIntPtrOrArray((int []){ 1, 2, 3, 4 }); 

..e cose simili può essere fatto con le strutture.

+0

grazie mille, mi ha salvato un sacco di pazienza! –

+2

Purtroppo non funziona in C++. Si ottiene l'errore "prendendo l'indirizzo della matrice temporanea". – Timmmm

+0

Non funziona su Visual Studio 2017 (v141) – sergiol

2

Se initializer_list non è disponibile, e gli array sono per lo più piccole, c'è un'altra opzione, il sovraccarico << operatore per std :: vector in questo modo:

template <typename T> 
inline std::vector<T> operator <<(const std::vector<T>& vec, const T& val) { 
    std::vector<T> result(vec); 
    result.push_back(val); 
    return result; 
} 

Con questo, si può fare questo:

void foo (const std::vector<int>& inputs) { 
    // ... 
} 

foo (std::vector<int>() << 10 << 20 << 30); 

C'è un prezzo da pagare per questa convenienza dell'inizializzazione di linea singola e non è necessario specificare la dimensione del vettore. Una copia del vettore precedente viene creata per ogni elemento che viene aggiunto, rendendo il tempo di esecuzione almeno quadratico in termini di dimensioni vettoriali: ecco perché è più adatto per vettori e casi brevi quando le prestazioni non contano. C'è una soluzione migliore per C++ 11, come sottolineato nella risposta di Spraff.