Array - Anzahl Elemente
-
Dravere schrieb:
hustbaer schrieb:
Man kann keine Arrays an Funktionen übergeben

Und was ist das?
template<typename T, std::size_t SIZE> void foo(T(& array)[SIZE]) { }:p
Das ist eine Referenz auf ein Array, kein Array.
pass-by-value != pass-by-reference
:p
-
Stromberg_ schrieb:
Wie kann ich die Anzahl der Elemente eines Arrays herausbekommen?
Mit size() es sei denn natürlich du hast einen besonders guten Grund, C-Arrays zu benutzen

-
hustbaer schrieb:
Das ist eine Referenz auf ein Array, kein Array.
pass-by-value != pass-by-referenceDu hast gesagt, man kann keine Arrays an Funktionen übergeben. Du hast nichts gesagt, ob es eine Referenz oder eine Kopie sein soll :p
Aber ok, du willst eine Kopie? Gut:
#include <algorithm> // ... template<typename T, std::size_t SIZE> void foo(const T(& array)[SIZE]) { T copy[SIZE]; std::copy(array, array + SIZE, copy); // ... }Zufrieden?

Grüssli
-
Dravere schrieb:
Zufrieden?

Kaum, denn übergeben wird es immer noch als Referenz. :p
-
Dravere schrieb:
hustbaer schrieb:
Das ist eine Referenz auf ein Array, kein Array.
pass-by-value != pass-by-referenceDu hast gesagt, man kann keine Arrays an Funktionen übergeben. Du hast nichts gesagt, ob es eine Referenz oder eine Kopie sein soll :p
Aber ok, du willst eine Kopie? Gut:
#include <algorithm> // ... template<typename T, std::size_t SIZE> void foo(const T(& array)[SIZE]) { T copy[SIZE]; std::copy(array, array + SIZE, copy); // ... }Zufrieden?

Grüssli
Bei "pass by reference" wird eine Referenz übergeben, nicht "das Array (als Referenz)" ("das Array als Referenz" ist in sich schon Unsinn, da man ein Array nicht in eine Referenz konvertieren kann).
Deine Funktion nimmt im übrigen auch nur eine Referenz. Dass diese const ist ändert daran nichts. Dass du dann intern eine Kopie anlegst ändert auch nichts. Und auch dass du ein Template verwendest um den Typ sowie die Grösse des Arrays deduzieren zu lassen ändert daran nichts.
Am nähesten kommt man dem "Übergeben von Arrays" IMO noch damit, dass man das Array in eine struct/class wrappt, wie es z.b. boost::array macht.
-
Falls auch reinzuföllig Vektoren gemeint sein könnten:
std::vector<int> Array(20); Array.size();
-
hustbaer schrieb:
Bei "pass by reference" wird eine Referenz übergeben, nicht "das Array (als Referenz)" ("das Array als Referenz" ist in sich schon Unsinn, da man ein Array nicht in eine Referenz konvertieren kann).
Es tut mir ja leid, aber das ist doch absoluter Unsinn.
Worauf referenziert diese übergebene Referenz? Oh, auf das Array. Daher sagt man dem, man übergibt das Array als Referenz, was mit konvertieren im übrigen überhaupt nichts am Hut hat. Man greift über die Referenz auf das Array zu. Wenn nach deiner Auffassung das Array nicht übergeben wurde, dann könnte man mit der Referenz gar nicht darauf zugreifen.
Schliesslich, gibt es gar keine Referenzen als Objekt. Du kannst also eigentlich gar keine Referenz übergeben, da es eigentlich die Referenz als Objekt nicht existiert. Auch im neuen Draft des Standards steht (habe den alten hier nicht), dass eine Referenz als Name auf das Objekt, welches die Referenz referenziert, verstanden werden kann. Wir übergeben somit das Array mit einem neuen Namen.hustbaer schrieb:
Dass diese const ist ändert daran nichts.
Schlaumeier. Das const habe ich sicher nicht hingeschrieben, um daran etwas zu ändern. Da geht es nur darum, dass man das ursprüngliche Array nicht verändern kann. Damit ich nämlich selber die Kopie erzeugen kann.
hustbaer schrieb:
Dass du dann intern eine Kopie anlegst ändert auch nichts.
Ich erweitere damit einfach den Funktionsaufruf. Am Ende habe ich genau das, was passiert wäre, wenn das Array als Kopie übergeben wurde. Ich habe es einfach selber gemacht. Es war ja auch nicht all zu ernst gemeint. Aber die Smilies hast du anscheinend grossartig übersehen.
Erklär mal an dem Code hier, was passiert. Vor allem würde mich interessieren, wie eine Referenz plötzlich 40 Bytes gross sein kann. Ich bin äusserst gespannt, wie du an dem Code abstreiten willst, dass das Array als Referenz übergeben wurde.
#include <algorithm> template<typename T, std::size_t SIZE> void foo(T (&ref)[SIZE]) { std::cout << sizeof(ref) << std::endl; ref[5] = 5; } int main() { int arr[10]; std::fill_n(&arr[0], 10, 0); int (&ref)[10] = arr; std::cout << sizeof(ref) << std::endl; foo(arr); ref[3] = 3; for(int i = 0; i < 10; ++i) { std::cout << arr[i] << ", "; } return 0; }Ausgabe:
40 40 0, 0, 0, 3, 0, 5, 0, 0, 0, 0,Grüssli
-
Dravere, ich vermute du weisst schon genau was ich meine. Hier mit Code um sich zu werfen bringt wohl nicht mehr viel.
Wenn ich sage "das Array wird übergeben", meine ich in diesem Fall es wird by-value übergeben, und genau das geht in C++ nicht, da sind wir uns ja denke ich einig.
-
Dravere schrieb:
Erklär mal an dem Code hier, was passiert. Vor allem würde mich interessieren, wie eine Referenz plötzlich 40 Bytes gross sein kann.
#include <algorithm> template<typename T, std::size_t SIZE> void foo(T (&ref)[SIZE]) { std::cout << sizeof(ref) << std::endl; ref[5] = 5; } int main() { int arr[10]; std::fill_n(&arr[0], 10, 0); int (&ref)[10] = arr; std::cout << sizeof(ref) << std::endl; foo(arr); ref[3] = 3; for(int i = 0; i < 10; ++i) { std::cout << arr[i] << ", "; } return 0; }Ausgabe:
40 40 0, 0, 0, 3, 0, 5, 0, 0, 0, 0,Grüssli
das ist leicht damit erklärt, daß die sizeof-funktion nicjt die größe der referenz, sondern die größe des dinges, wo die referenz hinzeigt, anzeigt.
wenn dur die größe der referenz wirklich anschauen willst, mußt du das so machen:
template<typename T, std::size_t SIZE> void foo(T (&ref)[SIZE]) { struct Test { T (&ref)[SIZE]; }; std::cout << sizeof(Test) << std::endl; }ausgabe: 4
also hat die referenz 4 bytes.
-
call-by-value
template<class T, unsigned size> struct value_array { T t[size]; }; template<class T, unsigned size> void func(<value_array<T, size> arr) { // arr ist eine kopie! } int main() { value_array<int, 50> arr; func(arr); // kopie! }:p :p
-
helferlein schrieb:
call-by-value
template<class T, unsigned size> struct value_array { T t[size]; }; template<class T, unsigned size> void func(<value_array<T, size> arr) { // arr ist eine kopie! } int main() { value_array<int, 50> arr; func(arr); // kopie! }:p :p
ein nicht-array einfach array zu nennen und damit was über arrays zu beweisen, das geht sogar noch einfacher.
void f(int arr)//call by value { } int main() { int array; f(array); }
-
@hustbaer,
Der erste Post war nicht so ernst gemeint. Der zweite Post war immer noch eher witzig gemeint. Da war ich ja mehr oder weniger immer mit dir einverstanden. Aber was du dann geschrieben hast. Naja, ich muss mich ja nicht nochmals wiederholen
Man kann nunmal etwas auf zwei Arten übergeben. Dass du zu Beginn pass-by-value meintest, ist für die meisten sicher klar. Deshalb war auch das Smilie da
@volkard,
Der Sinn des Codes war aber zu zeigen, dass man keinen Zeiger hat, sondern eben das übergebene Array.
Der sizeof Operator gibt natürlich bei einer Referenz die grösse des Objektes zurück, auf welche die Referenz referenziert. Laut Standard hat die Referenz keinen adressierbaren Speicher und die grösse ist nicht definiert. Dadurch ist nicht mal sicher, dass das ref in der Struktur Test gleich gross ist, wie das ref, welches im Funktionskopf deklariert wurde. Das hat ja auch den Zweck, dass die Referenz komplett wegoptimiert werden kann, wodurch man direkt mit dem Objekt arbeitet. Es wurde eben das Objekt übergeben.
Aber ich nehm mal an, dass du das selber weisst
Grüssli
-
Dravere schrieb:
@volkard,
Der Sinn des Codes war aber zu zeigen, dass man keinen Zeiger hat, sondern eben das übergebene Array.
Der sizeof Operator gibt natürlich bei einer Referenz die grösse des Objektes zurück, auf welche die Referenz referenziert. Laut Standard hat die Referenz keinen adressierbaren Speicher und die grösse ist nicht definiert. Dadurch ist nicht mal sicher, dass das ref in der Struktur Test gleich gross ist, wie das ref, welches im Funktionskopf deklariert wurde. Das hat ja auch den Zweck, dass die Referenz komplett wegoptimiert werden kann, wodurch man direkt mit dem Objekt arbeitet. Es wurde eben das Objekt übergeben.
Aber ich nehm mal an, dass du das selber weisst
ja, aber du hast es sehr schön zusammengefaßt.
weil nicht definiert ist, daß die referenz zum beispiel innendrin nur ein zeiger ist (wie zufällig bei allen mir bekannten implementierungen), sondern weil die compilerbauer da größte freiheiten haben, kann man echt nicht widersprechen, wenn du sagst, daß nicht eine referenz auf ein array übergeben wurde, sondern daß das array per referenz übergeben wurde.
zu sagen "man kann arrays nicht übergeben" ist nicht haltbar, fürchte ich.
-
volkard schrieb:
zu sagen "man kann arrays nicht übergeben" ist nicht haltbar, fürchte ich.
Hmm. Ja. Vielleicht eher das hier:
Man kann arrays nicht by value übergeben im herkömmlichen Sinne. Respektive es wird keine völlig neue, unabhängige Entität per Kopie erzeugt.
-
drakon schrieb:
volkard schrieb:
zu sagen "man kann arrays nicht übergeben" ist nicht haltbar, fürchte ich.
Hmm. Ja. Vielleicht eher das hier:
Man kann arrays nicht by value übergeben im herkömmlichen Sinne. Respektive es wird keine völlig neue, unabhängige Entität per Kopie erzeugt.Womit wir bei einer genaueren ("korrekteren"), aber für Anfänger vermutlich total unverständlichen Formulierung wären

-
hustbaer schrieb:
drakon schrieb:
volkard schrieb:
zu sagen "man kann arrays nicht übergeben" ist nicht haltbar, fürchte ich.
Hmm. Ja. Vielleicht eher das hier:
Man kann arrays nicht by value übergeben im herkömmlichen Sinne. Respektive es wird keine völlig neue, unabhängige Entität per Kopie erzeugt.Womit wir bei einer genaueren ("korrekteren"), aber für Anfänger vermutlich total unverständlichen Formulierung wären

MIST!
ja, deine formulierung war so hübsch und anfängerfortbringend, daß ich mir überlegt hatte, sie in meine sig aufzunehmen. die welt ist gemein.
-
Also um Anfänger ging es ja seit dem 3. Post nicht mehr.
