2009-11-18 9 views
12

Fondamentalmente mi piacerebbe fare qualcosa di simile:Passare attorno a matrici di dimensioni fisse in C++?

int[3] array_func() 
{ 
    return {1,1,1}; 
} 

int main(int argc,char * argv[]) 
{ 
    int[3] point=array_func(); 
} 

Ma questo non sembra legale in C++. So che posso usare i vettori, ma poiché so che la dimensione dell'array è una costante, sembra che si verifichi una perdita di prestazioni. Vorrei anche evitare un new se possibile, perché l'allocazione di elementi nello stack è più semplice e probabilmente anche per migliorare le prestazioni.

Qual è la soluzione qui?

risposta

13

con C++ 0x, il quasi finalizzato nuovo standard C++ (già implementato negli ultimi gcc e msvc IIRC), puoi farlo esattamente come vuoi! Basta usare std :: array invece di int [3].

std::array<int, 3> array_func() 
{ 
    return {1,1,1}; 
} 

int main(int argc,char * argv[]) 
{ 
    std::array<int, 3> point = array_func(); 
} 
18

È possibile avvolgerla in un struct, per renderlo restituibile per valore:

struct Vec3 
{ 
    float x[3]; 
} 

Vec3 array_func() 
{ 
    Vec3 x = { 1.f, 1.f, 1.f }; 

    return x; 
} 

non credo che è possibile utilizzare la sintassi di matrice inizializzazione direttamente l'istruzione return. Naturalmente si potrebbe introdurre un costruttore (le strutture sono solo classi con tutti i membri pubblici, dopo tutto):

struct Vec3 
{ 
    Vec3(a, b, c) 
    { 
    x[0] = a; 
    x[1] = b; 
    x[2] = c; 
    } 

    float x[3]; 
} 

Vec3 array_func() 
{ 
    return Vec3(1.f, 1.f, 1.f); 
} 
+4

Questa sarebbe la migliore risposta tranne che una tale struttura esiste già: http://stackoverflow.com/questions/1755000/1755017#1755017 – sbi

+7

l'ho scelta come risposta migliore perché risponde alla mia domanda, semplice e semplice, senza spingere una biblioteca che non ho chiesto. Non che la risposta di litb sia cattiva, ho appena trovato la risposta di unwind un po 'più chiara. –

+3

"... spingendo una biblioteca che non ho chiesto ..." Bene, stiamo parlando di _boost_ qui, non solo di una libreria. Comunque, ci sono buone probabilità che la tua implementazione di lib standard sia fornita con 'std :: tr1 :: array' (C++ 03 o TR1) o anche' std :: array' (C++ 1x), che è esattamente lo stesso . (Che va a dimostrare che boost non è solo un'altra libreria: è un banco di prova per il prossimo standard C++, fondato dai membri del comitato std per esattamente questo motivo, ha degli alti standard di qualità e recensioni impegnative, e sta contribuendo con un sacco di roba alla prossima libreria standard. – sbi

21

Mettere l'array in una struct. boost::array è un tale pacchetto:

boost::array<int, 3> array_func() { 
    boost::array<int, 3> a = {{ 1, 1, 1 }}; 
    return a; 
} 

int main() { 
    boost::array<int, 3> b = array_func(); 
} 

veloce e sporco:

template<typename E, size_t S> 
struct my_array { 
    E data[S]; 
}; 

Notate come è possibile utilizzare la sintassi di inizializzazione aggregata.

+0

Non capisco perché questo sia sovralimentato così tanto, l'uso di funzionalità linguistiche standard (in questo caso, una semplice struttura) è molto più pulito e veloce che invocare boost. Anche se raccomando la struttura a template usata qui - questa è la soluzione più semplice che è più riutilizzabile e che cosa avrei fatto. – KomodoDave

+0

@KomodoDave sei consapevole che puoi fare "sed, boost, std," nel mio frammento sopra e non hai nemmeno bisogno di "una semplice struttura"? evviva, siamo atterrati al 2011! a volte invocare la "spinta gonfia" (suppongo) può rivelarsi alla fine portare a meno gonfiarsi di reinventare la ruota. –

+2

@KomodoDave Vorrei suggerire downvoting di risposte errate e quelle che non rispondono veramente alla domanda. Questa risposta mi sembra ok. – jweyrich

2

non è possibile restituire una matrice di dimensioni fisse in C++. è possibile restituire un puntatore a int (che verrebbe utilizzato come matrice) ma che richiederebbe l'allocazione dell'array nell'heap utilizzando new.

in ogni caso, è possibile passare l'array come argomento alla funzione:

void array_func(int result[3]) 
{ 
    result[0] = 1; 
    result[1] = 1; 
    result[2] = 1; 
} 

int main(int argc,char * argv[]) 
{ 
    int point[3]; 
    array_func(point); 
} 

tuttavia, questo sembra più C di C++ ...

+0

nuovo non è necessario necessariamente. È anche possibile rendere statico l'array all'interno della funzione array_func (se ciò è possibile dipende ovviamente) – Christian

+1

Um, non è che '3' nella dichiarazione dei parametri è stato ignorato? – sbi

+0

sì hai ragione, finalmente, non sono nemmeno sicuro che compili. potrebbe essere necessario omettere la dimensione dell'array nella dichiarazione della funzione ... –

0

boost::array è un wrapper per un array basato su stack.

Nota che l'allocazione dello stack è destinata a rimanere più economica rispetto all'utilizzo di "nuovo" quando non devi copiare grandi array in giro.