2013-04-09 13 views
17

Es gibt eine Reihe basierte for-Schleife mit der Syntax:bereichsbasierte for-Schleife auf einem dynamischen Array?

for(auto& i : array) 

Es arbeitet mit konstanter Arrays, aber nicht mit Zeigern basierten dynamisch diejenigen, wie

int *array = new int[size]; 
for(auto& i : array) 
    cout<< i << endl; 

Es gibt Fehler und Warnungen über das Scheitern der Substitution, zum Beispiel:

Error] C:\Users\Siegfred\Documents\C-Free\Temp\Untitled2.cpp:16:16: error: no matching function for call to 'begin(int*&)'

Wie verwende ich diese neue Syntax mit dynamischen Arrays?

+2

was Sagen die Fehler? Mindestens post ** ein ** Fehler – Default

+1

es heißt Range-basierte für Schleife und SO und Google haben Tonnen von Beispielen – stijn

+0

[Fehler] C: \ Benutzer \ Siegfred \ Dokumente \ C-Free \ Temp \ Untitled2.cpp: 16: 16: error: keine passende Funktion für den Aufruf von 'begin (int * &)' –

Antwort

19

Um die Verwendung der bereichsbasierte for-Schleife Sie haben, um entweder begin() und end() Mitgliederfunktionen oder Überlastung des Dritt begin() und end() Funktionen zu machen. Im letzteren Fall können Sie Ihr Angebot in einer std::pair und Überlastung begin() und end() für diejenigen, wickeln:

namespace std { 
     template <typename T> T* begin(std::pair<T*, T*> const& p) 
     { return p.first; } 
     template <typename T> T* end(std::pair<T*, T*> const& p) 
     { return p.second; } 
    } 

Jetzt können Sie die for-Schleife wie folgt verwenden:

for (auto&& i : std::make_pair(array, array + size)) 
     cout << i << endl; 

Hinweis, dass das nicht-Mitglied begin() und end() Funktionen müssen hier im std Namespace überlastet werden, da pair liegt auch im Namensraum std. Wenn Sie nicht das Gefühl, mit den Standard-Namespace wie Manipulation, können Sie einfach Ihre eigenen kleine Paar Klassen erstellen und überlasten begin() und end() in Ihrem Namensraum.

Oder eine dünne Hülle um Ihren dynamisch zugewiesenen Array erstellen und begin() und end() Member-Funktionen bieten:

template <typename T> 
    struct wrapped_array { 
     wrapped_array(T* first, T* last) : begin_ {first}, end_ {last} {} 
     wrapped_array(T* first, std::ptrdiff_t size) 
      : wrapped_array {first, first + size} {} 

     T* begin() const noexcept { return begin_; } 
     T* end() const noexcept { return end_; } 

     T* begin_; 
     T* end_; 
    }; 

    template <typename T> 
    wrapped_array<T> wrap_array(T* first, std::ptrdiff_t size) noexcept 
    { return {first, size}; } 

Und Ihr Aufrufort sieht wie folgt aus:

for (auto&& i : wrap_array(array, size)) 
     std::cout << i << std::endl; 

Example

16

Sie können nicht Entfernungs-for-Schleife verwenden, mit dynamisch zugewiesenen Arrays, da Compiler nicht ableiten kann dieses Arrays beginnen und enden. Sie sollten immer Behälter verwenden, anstatt es zum Beispiel std::vector.

+0

@Zoidberg, bearbeitet, danke :) – soon

+1

nun, es hat funktioniert! Ich wusste nie, dass C++ typsicher ist, ich kam von C, also gewöhnte ich mich daran, dynamische und konstante Arrays auf die gleiche Weise zu manipulieren. –

+0

@MauriceRodriguez Nun, * C * hat genau diesen Unterschied zwischen Arrays und Zeigern. Zum Beispiel gibt 'sizeof (array)' in * C * auch völlig andere Dinge zurück, abhängig davon, ob es sich um 'int * array = malloc (N * sizeof (int)); 'oder' int array [N]; '. Es ist also nur, weil * C * es dir leichter gemacht hat * diesen Unterschied * falsch * zu ignorieren, nicht, dass dieser Unterschied nicht vorhanden wäre. –

8

Sie können keine bereichsbasierte Schleife über ein dynamisch zugewiesenes Array ausführen, da Sie lediglich einen Zeiger auf das erste Element haben. Es gibt keine Informationen über seine Größe, die der Compiler zum Ausführen der Schleife verwenden kann. Die idiomatische C++ Lösung wäre, die dynamisch zugewiesen Array durch ein std::vector zu ersetzen:

std::vector<int> arr(size); 
for(const auto& i : arr) 
    std::cout<< i << std::endl; 

Ein Bereich basierend für Loop funktioniert für std::array Objekte. Sie haben über die Array-Instanz suchen (arr), nicht der Typ (array):

std::array<int,10> arr; 
for(const auto& i : arr) 
    std::cout<< i << std::endl; 
+1

Sie können bereits über ein bloß automatisch zugewiesenes Array "forfor", also müssen Sie nicht nur die Wrapper-Klasse hinzufügen. 'int a [] {1, 2, 3}; for (auto it: a) std :: cout << it << ''; 'Jede Anzahl von Elementen erzeugt einen eindeutigen Typ, für den beim Kompilieren der Schleife" end "abgeleitet werden kann. –

-1

Sehen Sie diese Seite http://www.codeproject.com/Articles/570638/Ten-Cplusplus11-Features-Every-Cplusplus-Developer und finden Sie im Kapitel "Nicht-Mitglied() und end() beginnen". Dies könnte sein, was Sie erreichen möchten.

+0

Sie können direkt zu diesem Kapitel durch den Anker # Beginend verknüpfen, so [wie dieses] (http://www.codeproject.com/Articles/570638/Ten-Cplusplus11-Features-Every-Cplusplus-Developer#beginend). – Default

+2

Sie sollten versuchen, den Inhalt dessen hinzuzufügen, was der Benutzer lesen soll, da [nur Linkantworten nicht empfohlen werden] (http://meta.stackexchange.com/questions/8231/are-answers-that-just-contain) -links-woanders-wirklich-gute-antworten). – Default

+0

"Das könnte sein, was Sie erreichen wollen." Nein, kann es nicht. Es würde einen Weg erfordern, um die Größe/das letzte Element für ein dynamisches Array abzuleiten, wenn nur eine Instanz seines generischen Typs verwendet wird, was nicht möglich ist ... und aus der Tatsache ersichtlich sein sollte, dass solche Funktionen dafür nicht bereits vorgesehen sind genauer Grund. –