2012-03-08 15 views
18

So che posso fare questo in C++:C++ stringa di gamma di inizializzazione

string s[] = {"hi", "there"}; 

Ma c'è comunque di delcare una matrice in questo modo, senza delcaring string s[]?

ad es.

void foo(string[] strArray){ 
    // some code 
} 

string s[] = {"hi", "there"}; // Works 
foo(s); // Works 

foo(new string[]{"hi", "there"}); // Doesn't work 
+3

perché utilizzare array c-style allocati dinamicamente? Ti suggerirei di usare 'std :: vector' invece. Quando usi C++ 11 puoi costruirli usando gli elenchi di inizializzazione, ad es. 'void foo (vector ); foo ({"hi", "there"}); 'dovrebbe funzionare in C++ 11 – Grizzly

risposta

18

In C++ 11 puoi. Una nota in anticipo: non lo new array, non ce n'è bisogno.

Primo, string[] strArray è un errore di sintassi, che dovrebbe essere string* strArray o string strArray[]. E presumo che sia solo per l'esempio che non passi alcun parametro di dimensione.

#include <string> 

void foo(std::string* strArray, unsigned size){ 
    // do stuff... 
} 

template<class T> 
using alias = T; 

int main(){ 
    foo(alias<std::string[]>{"hi", "there"}, 2); 
} 

Nota che sarebbe stato meglio se non hai bisogno di passare la dimensione della matrice come un parametro in più, e per fortuna c'è un modo: modelli!

template<unsigned N> 
void foo(int const (&arr)[N]){ 
    // ... 
} 

Si noti che questo corrisponderà solo gli array di stack, come int x[5] = .... O quelli temporanei, creati dall'uso di alias sopra.

int main(){ 
    foo(alias<int[]>{1, 2, 3}); 
} 
4

Con il supporto per C++ 11 inizializzazione elenca è molto facile:

#include <iostream> 
#include <vector> 
#include <string> 
using namespace std; 

using Strings = vector<string>; 

void foo(Strings const& strings) 
{ 
    for(string const& s : strings) { cout << s << endl; } 
} 

auto main() -> int 
{ 
    foo(Strings{ "hi", "there" }); 
} 

in mancanza di tale (ad esempio per Visual C++ 10.0) si possono fare cose come questa:

#include <iostream> 
#include <vector> 
#include <string> 
using namespace std; 

typedef vector<string> Strings; 

void foo(Strings const& strings) 
{ 
    for(auto it = begin(strings); it != end(strings); ++it) 
    { 
     cout << *it << endl; 
    } 
} 

template< class Elem > 
vector<Elem>& r(vector<Elem>&& o) { return o; } 

template< class Elem, class Arg > 
vector<Elem>& operator<<(vector<Elem>& v, Arg const& a) 
{ 
    v.push_back(a); 
    return v; 
} 

int main() 
{ 
    foo(r(Strings()) << "hi" << "there"); 
} 
+1

Molto verboso: usa un ciclo basato su intervalli:' for (auto s: stringhe) cout << s << endl; ' – rwst

+0

@rwst: Sì, oggi lo è. Grazie. Probabilmente * ho usato gli iteratori per supportare il Visual C++ comune nel 2012. Il semplice loop che si mostra ha una leggera inefficienza in quanto copia le stringhe ma (1) è insignificante rispetto all'io nel corpo del ciclo e (2) è comunque irrilevante, dal momento che non si tratta di questo esempio, e (3) una riscrittura per l'efficienza (non insegnare cattivi idiomi) non è difficile da capire. Quindi, dal 2015 non vedo alcun motivo per mantenere il ciclo iteratore che ho usato. Sentiti libero di sistemare. :) –

+0

@rwst: OK l'ho aggiornato io stesso. Controlla anche che l'esempio di Visual C++ 10 sia effettivamente compilato con VC10. Quando l'ho guardato ora, non mi ricordavo che VC10 supportasse i riferimenti di valore, ma lo ha fatto (almeno il codice compila e produce il risultato corretto). –