ubuntuusers.de

Arrays als Wertparameter in C++ ???

Status: Gelöst | Ubuntu-Version: Nicht spezifiziert
Antworten |

Diogenes77

Avatar von Diogenes77

Anmeldungsdatum:
22. November 2007

Beiträge: 174

Wohnort: /home

Hi,
ich schaue mir gerade C++ ein wenig an, sehr mächtig + sehr komplex (das erste bedingt wohl das zweite), gefällt mir aber ausgesprochen gut ☺
Habe ein kleines Problemchen mit Arrays als Wertparameter. In einer Funktion f, die ein Array feld als Wertparameter bekommt, möchte ich die Anzahl der Elemente des übergebenen Arrays ermitteln. Das berechne ich so: sizeof(feld) / sizeof(*feld). Das Problem ist aber, dass in der Funktion sizeof(feld) IMMER 4 zurückliefert. Im Hauptprogramm, wo das Array deklariert ist, liefert sizeof die richtige Grösse. Um das verständlicher zu machen, hier ist das Program (sonstiger Code rundherum ist gelöscht) :

#include <iostream>
using namespace std;

void f (int feld[]) {
  cout << "function f:  " <<  "sizeof(feld) / sizeof(*feld) =  "
       << sizeof(feld) << " / " << sizeof(*feld)  << endl;
}
int main()
{
  int arr[] = {4711, 69, 0};
  cout << "main:        " << "sizeof(arr)  / sizeof(*arr)  = "
       << sizeof(arr) << " / " << sizeof(*arr)  << endl;
  f(arr);
  return 0;
}

/* Output des Programms:
main:        sizeof(arr)  / sizeof(*arr)  = 12 / 4
function f:  sizeof(feld) / sizeof(*feld) =  4 / 4
Press Enter to continue!
*/

Ein Array-Name ist die Adresse des 1. Elements. Bei der Wert-Übergabe des Arrays an die Funktion würde ich mir erwarten, dass eine Kopie des GESAMTEN Arrays übergeben wird. Es wird aber in Wirklichkeit nur eine Kopie des POINTERS auf das Array übergeben! Der Aufruf sizeof liefert folglich nur die Grösse eines Pointers, nicht die Grösse des Array selbst. Offensichtlich haben die C++ Autoren das Klassenkonzept bis in allerletzte Konsequenz durchgehalten: Nachdem ein Array ein Pointer auf das 1. Element ist, und ein Pointer ein Built-in-Datentyp ist, gibts folglich kein Konstruktor, der das Objekt (= das Array) bei der Wertübergabe kopieren/initialisieren würde... ☹

Frage 1: Gibt es eine Möglichkeit, die Grösse des Arrays in der Funktion festzustellen ? Vom Aufrufer der Funktion zu verlangen, dass er die Grösse als Parameter mitgibt, möchte ich -wenn möglich- vermeiden.

Frage 2: Wie würde man eine Referenz an ein Array als Parameter übergeben? Wenn ich im o.g. Beispiel die Funktion so definiere

void f (int& feld[]) { // code}


beschwert sich der Compiler:

/home/pavel/IT/project/accelerated_cpp/kap10/problem/src/problem.cpp:5: Fehler: Deklaration von »feld« als array of references

Der ganze Sinn von call-by.-value und call-by-reference ist damit bei Arrays ausgehebelt: Ich bekomme IMMER nur eine REFERENZ auf das Original. Oder ist mir da etwas Wesentliches an C++ entgangen ????

T-Virus

Anmeldungsdatum:
5. Januar 2008

Beiträge: 183

Wohnort: Nörten-Hardenberg

Hallo,
versuchs mal mir einem Zeige zum Übergeben 😉
So kannst du das ganze auch bei größeren Arrays ordentlich beschleunigen, da du ja nur einen Zeiger, wahlweise auch eine Referenz, auf das Array übergibts ☺

Aber ein Array so übergeben habe ich auch noch nicht versucht.

EDIT
Werd Heuteabend mal gucken, was es da genau für Probleme gibt.

MFG T-Virus

Diogenes77

(Themenstarter)
Avatar von Diogenes77

Anmeldungsdatum:
22. November 2007

Beiträge: 174

Wohnort: /home

Du meinst die Funktion als void f (const int *feld) { /* Code */ } zu deklarieren ? Das ist aber dasselbe, als void f (int feld[]) { /* Code */ } und löst das Problem mit der Grössenberechnung nicht. (Der Output des Programms ist haargenau gleich).

Diogenes77

(Themenstarter)
Avatar von Diogenes77

Anmeldungsdatum:
22. November 2007

Beiträge: 174

Wohnort: /home

Noch zum Hintergrund meines Problems: Die Funktion soll den Median des Array berechnen, deshalb muss sie das Array vorher sortieren. Und es ist nicht erwünscht, dass als Nebeneffekt der Medianberechnung das Argument verändert (=sortiert) wird.

Bauer

Anmeldungsdatum:
28. Juni 2006

Beiträge: 333

Hallo,

du übergibst nicht das Feld an die Funktion, sondern einen Zeiger auf das erste Element des Feldes. Dieser Zeiger wird tatsächlich Call-by-Value übergeben. Nur wenn du einen Zeiger bit für bit kopierst, zeigt er hinterher auf das selbe Feld wie vorher. Deswegen hast du das Gefühl, dass Feld würde by-Reference übergeben. Was irgendwo ja auch das gleiche ist. Deswegen funktioniert dein Test auf die Größe übrigens auch nicht mehr.

int feld[] = {1, 2, 3, 4, 5}; // sizeof(feld) == 5*sizeof(int)

int f(int* feld)
{
    std::cout << sizeof(feld); // sizeof(feld) == sizeof(int*) Also die Größe eines Zeigers auf int
} 

Mir ist keine portable Lösung bekannt, ein Feld einer Funktion zu übergeben und danach noch zur Laufzeit herauszukriegen wie groß es ist.
Aber ein einfaches Feld zu benutzen ist in den meisten Situation eh Quatsch. Nimm std::vector, der nimmt dir die Arbeit dann ab.

Siehe auch hier

http://www.cppreference.com
www.c-plusplus.de

Gruß

Diogenes77

(Themenstarter)
Avatar von Diogenes77

Anmeldungsdatum:
22. November 2007

Beiträge: 174

Wohnort: /home

Danke für die Hinweise !! Das mit dem std::vector ist klar, aber wie gesagt, ich bin dabei, C++ zu lernen und da wollte ich zu Übungszwecken sowas wie eine eigene vector-Klasse implementieren (ohne auf std::vector zurück zu greifen, das wäre ja fad 😊 ). Dabei bin ich auf das o.g. Problem gestossen. lg

Bauer

Anmeldungsdatum:
28. Juni 2006

Beiträge: 333

Bei einer eigenen Vectorklasse lohnt es sich vielleicht die Größe und Kapazität in Attributen abzulegen. Dann haste das Problem auch nicht.

T-Virus

Anmeldungsdatum:
5. Januar 2008

Beiträge: 183

Wohnort: Nörten-Hardenberg

Hallo,
wäre auch günstig wenn du eine Art Resize Method schreibst, mit der du dein Array löscht und neu anlegst um die Größe zuändern 😉
Musst da aber mit dem Heap rumspielen aber weiß nicht ob es funktioniert 😮)

Hab mich von solchen Nachbauklassen immer ferngehalten.
Man lernt zwar gut aber die STL bietet mir genug um es nicht nachbauen zu müssen.

MFG T-Virus

sxfreak

Avatar von sxfreak

Anmeldungsdatum:
27. Juni 2006

Beiträge: 436

Hi

Also das is ne gute Idee so ne Nachbau-klasse. Meine is sogar kleiner und schneller als die STL Klasse (jedoch ohne Iterratoren). xD

Und ich benutz die auch in meinen Projekten also kann ich nur empfehlen.\^^

Bauer

Anmeldungsdatum:
28. Juni 2006

Beiträge: 333

Wobei ist deine schneller? Und was machst du anders, um das zu erreichen? Bin neugierig. Sonst lad einfach mal Code hoch.

Lunar

Anmeldungsdatum:
17. März 2006

Beiträge: 5792

Diogenes77 hat geschrieben:

sehr mächtig + sehr komplex (das erste bedingt wohl das zweite)

Sorry für OT, aber da muss ich einfach wieder sprechen! Es gibt nur einen sehr, sehr begrenzten Zusammenhang zwischen der Komplexität und der Mächtigkeit einer Sprache! Natürlich ist eine gewissen Grundkomplexität notwendig, um über reines Shell-Scripting hinaus zu kommen, aber man kann schon in bash komplexe Programme implementieren! Das Programm, welches unter Gentoo zum Auffinden und Korrigieren kaputter Linking-Informationen in Binaries verwendet wird, ist z.B. ein bash-Programm.
Hochsprachen wie Java, C# oder Python sind von wesentlich geringerem Sprachumfang und wesentlich geringerer Komplexität als C++ und trotzdem nicht eingeschränkt.

Bauer

Anmeldungsdatum:
28. Juni 2006

Beiträge: 333

Hochsprachen wie Java, C# oder Python sind von wesentlich geringerem Sprachumfang und wesentlich geringerer Komplexität als C++ und trotzdem nicht eingeschränkt.

Naja, ein bisschen schon, ne.
Aber du hast Recht, dass Komplexität und Mächtigkeit nicht zwingend zusammenhängen. Aber 'was ist hier eigentlich Mächtigkeit?

Lunar

Anmeldungsdatum:
17. März 2006

Beiträge: 5792

Bauer hat geschrieben:

Hochsprachen wie Java, C# oder Python sind von wesentlich geringerem Sprachumfang und wesentlich geringerer Komplexität als C++ und trotzdem nicht eingeschränkt.

Naja, ein bisschen schon, ne.

Ja, ich keine meine Hardware nicht direkt ansprechen, und keine Kernelmodule programmieren. Damit haben sie die Einschränkungen aber auch schon ziemlich schnell erledigt 😉

Bauer hat geschrieben:

Aber 'was ist hier eigentlich Mächtigkeit?

Die Mächtigkeit einer Sprache bestimmt, was man mit einer Sprache alles programmieren kann.

Apollon

Avatar von Apollon

Anmeldungsdatum:
27. Oktober 2004

Beiträge: 724

Wohnort: Darmstadt

Lunar hat geschrieben:

Bauer hat geschrieben:

Aber 'was ist hier eigentlich Mächtigkeit?

Die Mächtigkeit einer Sprache bestimmt, was man mit einer Sprache alles programmieren kann.

War eine gute Frage die "praktisch" beantwortet wurde. Prizipiell wird die Maechtigkeit an der Turing-Vollstaendigkeit gemessen. Dabei gibt es nur eine Entweder-Oder Antwort. Entweder ist eine Sprache Turing-Vollstaendig oder nicht. Sind zwei Sprachen Turing-Vollstaendig, sind sie gleichmaechtig. Soweit die Theorie...

Bauer

Anmeldungsdatum:
28. Juni 2006

Beiträge: 333

Was bringt mir bei Python die Turing-Vollständigkeit, wenn ich 'nen Treiber schreiben will. Darauf wollte ich schon hinaus. Das man sich dieses Mehr an 'Macht' bei C++ allerdings teuer erkauft, streite ich gar nicht ab.

Antworten |