2016-06-14 7 views
9

Warum dieses Stück Code:Unerkannte bereichsbasierte for-Schleife?

void printarray(int array[]) { 
    for (int x: array) { 
     std::cout << x << std::endl; 
    } 
} 

generiert diese Fehler bei der Kompilierung?

error: 'begin' was not declared in this scope 
    for (int x: array) { 

Was soll ich über bereichsbasierte for Schleifen vertun?

+6

In diesem Zusammenhang 'int array []' wirklich kein Array, sondern entspricht 'int * array'. Innerhalb der Funktion kennen wir die Größe des Parameters nicht. Siehe [Größe eines Arrays in der Programmiersprache C] (http://stackoverflow.com/questions/1975128/sizeof-an-array-in-the-c-programming-language) –

+0

Verwenden Sie den einfachsten Weg: void printarray (Std :: vector array) {... –

+0

@Bo Persson Konnte die Funktion Hilfe inlining? – user6245072

Antwort

5

Wenn ein Array als Argument einer Funktion übergeben wird, wird es implizit in Zeiger auf sein erstes Element konvertiert. Auch Parameter, die Arrays deklarieren, werden an Zeiger angepasst.

So zum Beispiel diese Funktionsdeklarationen

void printarray(int array[100]); 
void printarray(int array[10]); 
void printarray(int array[]); 

erklärt die gleiche Funktion und entspricht

void printarray(int *array); 

Sie müssen also wie zum Beispiel auch die Größe des Arrays an die Funktion zu übergeben

void printarray(const int array[]. size_t n) 
{ 
    for (size_t i = 0; i < n; i++) 
    { 
     std::cout << a[i] << std::endl; 
    } 
} 

Sie könnten eine Template-Funktion speziell für Arrays p schreiben durch Bezugnahme assed wie beispielsweise

template <size_t N> 
void printarray(const int (&array)[N]) 
{ 
    for (int x : array) 
    { 
     std::cout << x << std::endl; 
    } 
} 

oder

template <typename T, size_t N> 
void printarray(const T (&array)[N]) 
{ 
    for (auto x : array) 
    { 
     std::cout << x << std::endl; 
    } 
} 

jedoch im Vergleich mit der vorherige Funktion hat es einen Nachteil, da Arrays unterschiedlicher Größe sind verschiedene Typen und der Compiler so viele Funktionen aus der Vorlage erzeugen So viele Arrays unterschiedlicher Typen werden Sie mit der Funktion verwenden.

Und Sie könnten Standardalgorithmen wie zum Beispiel std::copy oder std::for_each verwenden, um ein Array auszugeben.

Zum Beispiel

#include <iostream> 
#include <algorithm> 
#include <iterator> 

int main() 
{ 
    int array[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 

    std::copy(std::begin(array), std::end(array), 
       std::ostream_iterator<int>(std::cout, "\n")); 

    return 0; 
} 

Ein weiterer Ansatz ist die Standardklasse verwenden std::array die entsprechenden Mitgliederfunktionen begin und end hat, die durch den Bereich für Aussagen beruht, verwendet werden. Zum Beispiel

#include <iostream> 
#include <array> 

const size_t N = 10; 

void printarray(const std::array<int, N> &array) 
{ 
    for (int x : array) std::cout << x << std::endl; 
} 

int main() 
{ 
    std::array<int, N> array = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 

    printarray(array); 

    return 0; 
} 

Aber in diesem Fall müssen Sie auch eine Template-Funktion schreiben, wenn Sie der Ausgabe Objekte der Klasse std::array mit unterschiedlichen Anzahlen oder Typen von Elementen werden.

Zum Beispiel

#include <iostream> 
#include <array> 

template <typename T, size_t N> 
void printarray(const std::array<T, N> &array) 
{ 
    for (auto x : array) std::cout << x << std::endl; 
} 

int main() 
{ 
    std::array<int, 10> array1 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 

    printarray(array1); 

    std::array<char, 10> array2 = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J' }; 

    printarray(array2); 

    return 0; 
} 
1

Der Parameter printarray empfängt ist eigentlich ein int *, der Bereich für würde nicht wissen, wo zu stoppen ist. In diesem Fall müssen Sie die Länge als Parameter senden und eine regelmäßige für

13

Ihr Problem ist, dass array ist eigentlich kein Array. Wenn Sie

void printarray(int array[]) 

schreiben, ist es das gleiche wie

void printarray(int* array) 

Da Sie nicht, wie viele Elemente ein Zeiger auf ohne zusätzliche Parameter Größe sagen, können Sie es nicht mit einer for-Schleife reichten Basis verwenden können.

Was Sie tun müssen, ist das Array als Referenz übergeben, so dass das Array nicht in einen Zeiger zerfällt. Wenn Sie die genaue Größe des Arrays kennen, dann können Sie

void printarray(int (&array)[size_you_want_here]) 

verwenden Wenn Sie die Funktion generische machen wollen, so kann es mit unterschiedlicher Größe Arrays arbeiten, dann können Sie eine Vorlage verwenden, wie

template<std::size_t N> 
void printarray(int (&array)[N]) 

I beide der oben genannten Fälle haben Sie jetzt ein tatsächliches Array anstelle eines Zeigers, so dass Sie es mit einer Entfernungsbasierten for-Schleife verwenden können.

Beachten Sie auch, können wir die Funktion vollständig generisch mit

template<typename T, std::size_t N> 
void printarray(T (&array)[N]) { 
    for (auto&& x : array) { 
     std::cout << x << "\n"; 
    } 
} 

Sie auch machen bemerke ich std::endl zu "\n" ändern. Normalerweise möchten Sie endl nicht verwenden, da es im Stream explizit flush() aufruft. In der Regel "\n" ist alles, was Sie brauchen und am Ende, wenn der Ausgang noch nicht geleert ist, können Sie flush() selbst anrufen.

+0

Warum 'auto && x' obwohl? – user6245072

+0

@ user6245072 Es ist nur aus Gewohnheit. Sie können auch 'const auto &' verwenden, um es nur lesen und referenzieren zu lassen. – NathanOliver