2013-01-21 10 views
5

Wygląda na to, że styl "dla każdego" składni dostępny w C++ 11 pozwala na iterację macierzy bez znajomości faktycznego rozmiaru tablicy (liczba elementów). Zakładam, że ponieważ jest to część nowego standardu, jest to całkowicie bezpieczne, nawet dla macierzy C. Zazwyczaj należy również oddzielnie znać rozmiar tablicy C przed manipulowanie go, ale chcę weryfikacji ze ktoś doświadczony z tej techniki nowy C++, że działa dokładnie tak, jak można się spodziewać:na podstawie pętli w C++

extern float bunch[100]; 

for (float &f : bunch) { 
    f += someNumber; 
} 

Czy jest coś I powinien wiedzieć o nieoczywistych efektach ubocznych lub wadach tej techniki? Nie pokazuje zbyt wiele w kodzie, który widzę, prawdopodobnie dlatego, że większość kodu została napisana, zanim znalazła się w standardzie. Chcesz się upewnić, że jego rzadkie użycie nie jest spowodowane innymi przyczynami, które nie są dobrze znane.

+10

Zawsze możesz znać rozmiar tablicy (https://gist.github.com/3959946#file-arrays-h-L33). Jeśli przekształcisz to w wskaźnik, przestaniesz znać rozmiar. –

+1

@ R.MartinhoFernandes: Niezły sens! –

+2

Ogólnie rzecz biorąc, będziesz żył o wiele szczęśliwszym życiem w stylu C++, niszcząc zwykłe tablice i przechodząc do standardowych kontenerów bibliotek. –

Odpowiedz

4

Nie ma w tym przypadku nic dziwnego ani niebezpiecznego. Rozmiar tablicy jest znany podczas kompilacji, więc można go użyć w pętli. Jest to przykład funkcji szablonu, który pozwala, aby dowiedzieć się długość tablicy:

template< class T, std::size_t N > 
std::size_t length(const T (&)[N]) 
{ 
    return N; 
} 

Foo f[5]; 
std::cout << length(f) << "\n"; 

Należy jasno powiedzieć, że nie można korzystać z tej techniki, lub pętle zakres oparte na dynamicznie wielkości C-style tablice.

Oczywiście, jeśli masz pętle oparte zakres następnie należy również mieć std::array (jeśli nie, prawdopodobnie można dostać Ti od std::tr1 lub Boost), dzięki czemu można uniknąć tablicę C-styl całkowicie:

extern std::array<float, 100> bunch; 

for (auto &f : bunch) { 
    f += someNumber; 
} 
+0

Ah, może moje pomylenie jest wtedy różnicą między tablicą C a 'std :: array' - bazuje ona na tym drugim, ale nie na pierwszym, prawda? Ponieważ zawsze myślałem i czytałem, że tablica C nie dostarcza wiedzy o jego własnym rozmiarze (długości) – johnbakers

+1

@SebbyJohanns nie, jest poprawna dla obu, o ile tablica typu C ma rozmiar statystyczny. Powyższa funkcja szablonu pokazuje, że możesz odzyskać rozmiar z takiej tablicy. – juanchopanza

+0

innymi słowy działa na tablicy na stosie, a nie na stercie, prawda? – johnbakers

2

Tablice można przekazywać jako referencje, a ich typ i długość można wywnioskować.

#include <iostream> 

template<typename T, size_t N> 
void fun(T const (&arr)[N]) 
{ 
    for (std::size_t i = 0; i < N; ++i) 
     std::cout << arr[i] << " "; 
} 

int main() 
{ 
    int x[] = { 1, 2, 3 }; // no need to set length here 
    fun(x); // 1 2 3, no need to specify type and length here 
} 
+1

Nie jest dla mnie jasne, w jaki sposób 'size_t' dla' N' jest przekazywane do funkcji 'zabawa' jak wyodrębnia wartość dla 'N'? – johnbakers

+0

Podczas dedukcji argumentu szablonu, kompilator analizuje argument (x, który jest typu int [3]) i formalny parametr (arr, który jest typu T [N]) i zastępuje int dla T i 3 dla N daje dokładny mecz. – TemplateRex

+0

@SebbyJohanns typ tablicy o stałym rozmiarze zawiera rozmiar. następnie użyj dedukcji parametru, aby ją uzyskać. – juanchopanza

4

Jest całkowicie bezpieczne używanie pętli for z macierzami. Przypuszczam, że obawiasz się, że możesz przypadkowo go użyć na wskaźniku:

float* array = new float[100]; 
for (float& f : array) { 
    // ... 
} 

Nie martw się. Kompilator spowoduje błąd w tym przypadku. Tak więc w przypadkach, w których nie jest to bezpieczne, i tak otrzymasz błąd kompilacji.

+0

To i tak byłaby jego własna głupota za używanie 'new []'. – Puppy

+0

@DeadMG co jest nie tak z 'new float [100]'? – johnbakers

+1

@DeadMG: "Głupi" to nie to samo, co "Niewiedza". –