Forum: PC-Programmierung C++: Objekte zwischen Methoden austauschen


von Maxim (Gast)


Lesenswert?

Wie es aussieht, kann man in C++ keine Objekte als Rückgabewert haben. 
Wenn ich nun eine Funktion habe, die mir aus vier Integern einen Vector 
erstellt und ich diesen Vector weiterverwenden will, wie bekomme ich ihn 
"aus der Methode raus"? Ich dachte da zuerst, der Methode einen Pointer 
zu übergeben, sodass die Methode diesen für die Ergebnisse benutzt. Ist 
dieser Ansatz richtig? Hat bei mir leider nicht geklappt ... Kann man in 
C++ eine Referenz auf ein Objekt einer Klasse zurückgeben? Oder wie wird 
das allgemein gehandhabt?

Java lässt grüßen ... ;)

von Sven P. (Gast)


Lesenswert?

Maxim schrieb:
> Wie es aussieht, kann man in C++ keine Objekte als Rückgabewert haben.
Nicht? Wär aber sonderbar...


> Wenn ich nun eine Funktion habe, die mir aus vier Integern einen Vector
> erstellt und ich diesen Vector weiterverwenden will, wie bekomme ich ihn
> "aus der Methode raus"? Ich dachte da zuerst, der Methode einen Pointer
> zu übergeben, sodass die Methode diesen für die Ergebnisse benutzt.
Kann man machen, muss man allerdings aufpassen, dass der Zeiger nach 
Verlassen der Methode auch noch irgendwohin zeigt. Bedenke, dass die 
Lebensdauer lokaler Variablen und Objekte dann nämlich endet!

> Ist
> dieser Ansatz richtig? Hat bei mir leider nicht geklappt ... Kann man in
> C++ eine Referenz auf ein Objekt einer Klasse zurückgeben?
Kann man, dann gilt aber gleiches. Auch eine Referenz kann auf ein nicht 
mehr existierendes Objekt verweisen. Das passt den meisten OOP-Priestern 
zwar nicht in den Kram, ist aber so.

> Oder wie wird
> das allgemein gehandhabt?
Ganz 'normal' halt -- entweder sich vorher einigen, wer ein Objekt 
erzeugt und wer es zerstört: Dann kann man auch ein neu erzeugtes Objekt 
als Zeiger zurückgeben (so von wegen 'return new ...'. Oder ein lokales 
Objekt direkt zurückgeben, das wird dann eben zur Kopie. Oder eine 
Referenz auf ein statisches Objekt -- ja nachdem, was grad passt.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Maxim schrieb:
> Wie es aussieht, kann man in C++ keine Objekte als Rückgabewert haben.
Welches spezielle C++ hast du den wo das nicht geht?
Also bei mir klappt das wunderbar ;)
1
std::vector blabla() {
2
 std::vector v;
3
 v.push_back(1);
4
 v.push_back(2);
5
 v.push_back(3);
6
 v.push_back(4);
7
 return v;
8
}
Alternativ:
1
blabla(std::vector& v) {
2
 v.push_back(1);
3
 v.push_back(2);
4
 v.push_back(3);
5
 v.push_back(4);
6
}
(ungetestet nur vom Prinzip her!)
Und bitte bitte keine Pointer wenns geht: 
http://www.parashift.com/c++-faq-lite/references.html
Die Seite ist allgemein recht gut zum "querlesen" wenn man bei C++ 
einsteigt.

von Karl H. (kbuchegg)


Lesenswert?

Sven P. schrieb:
> Oder ein lokales
> Objekt direkt zurückgeben, das wird dann eben zur Kopie.

Davor sollte man allerdings keine Scheu haben.
Der C++ Weg ist es, ganz einfach das Objekt zurückzugeben.

Es gibt eine einzige Optimierung, die im C++ Standard erwähnt und 
ausdrücklich erlaubt wird. Die sog. Named Return Value Optimization

Sie kommt hier zum tragen
1
class A
2
{
3
};
4
5
6
A foo()
7
{
8
  A objOfA;
9
10
  return objOfA;
11
}
12
13
int main()
14
{
15
  A test;
16
17
  test = foo();
18
}

ZUnächst mal würde man annehmen, dass das Objekt in der Funktion kopiert 
wird, diese Kopie aus der Funktion herausgereicht wird, dort mittels 
einem op= zugewiesen wird und danach das temporäre Objekt zerstört wird. 
Alles in allem eine aufwändige Sache.

Wenn da nicht die NRVO wäre.

Sie erlaubt explizit, dass der Compiler da ein paar Schritte 
überspringt, zb indem das temporäre Objekt nicht erzeugt wird, sondern 
test seinen Zuweisung direkt von objOfA erhält. Eine weitere Möglichkeit 
ist es, dass der Compiler die Situation so löst, dass er eine Referenz 
auf test in die Funktion hinein übergibt, und objOfA inplace im test 
Objekt konstruiert.

In all diesen Fällen erfolgt dann kein Aufruf des Copy Constructors bzw. 
von Destruktoren. Und das ist explizit erlaubt, selbst wenn diese Member 
Funktionen Nebeneffekte haben (*)

Fazit: keine Angst davor, Objekte direkt aus einer Funktion heraus als 
Return Wert zu liefern. Compiler haben Methoden, wie sie auch diese 
Fälle schnell machen können.

(*) Das ist einer der Gründe, warum man nicht zu clever sein sollte und 
im Copy Construktor andere Funktionalität als einfach nur 'Erzeuge eine 
Kopie des Objektes' unterbringen sollte.

von der mechatroniker (Gast)


Lesenswert?

Schließe mich den Vorpostern an. Objekt zurückgeben, oder wenn zwingende 
Gründe dagegen sprechen, einen std::auto_ptr darauf.

von jua (Gast)


Lesenswert?

Dass ein Compiler es möglicherweise optimieren kann, ist IMO kein guter 
Grund, ineffizienten Code zu schreiben.

von Karl H. (kbuchegg)


Lesenswert?

jua schrieb:
> Dass ein Compiler es möglicherweise optimieren kann, ist IMO kein guter
> Grund, ineffizienten Code zu schreiben.

Was ist bei dir ineffizient?

Letzten Endes, wenn mein dein Argument ins Extrem treibt, bedeutet es: 
Alles ausser Assembler ist Müll :-)


Mach dir um Effizenz keine Sorgen. C++ Compiler sind viel besser als du 
glaubst. Schon so mancher C Trickser, der auf seiner Überlegenheit 
gepocht hat, hat sein blaues Wunder erlebt, als der C++ Compiler aus 
einem ordinärem, schön geschriebenen, kanonischen C++ Programm etwas 
erzeugt hat, was seine 'hoch-optimierte' C-Lösung alt aussehen hat 
lassen. Von "korrekter Fehlerbehandlung" versus "wieder einmal in C 
nicht freigegebenem Speicher" reden wir erst mal gar nicht.

Wenn du Effizienz haben willst, denn leg dein Augenmerk auf Algorithmen. 
Die Details der Implementierung überlass getrost dem Compiler.

von Rolf Magnus (Gast)


Lesenswert?

jua schrieb:
> Dass ein Compiler es möglicherweise optimieren kann, ist IMO kein guter
> Grund, ineffizienten Code zu schreiben.

Daß eigentlich alle gängigen Compiler hier den effizienten Weg 
automatisch verwenden, ist ein guter Grund, einfacheren, lesbareren Code 
zu schreiben. Im Falle von Operatorüberladung, z.B. beim Operator+ 
geht's auch gar nicht anders.

Maxim schrieb:
> Wie es aussieht, kann man in C++ keine Objekte als Rückgabewert haben.

Du kannst das vielleicht nicht, aber "man" kann das schon ;-)

> Wenn ich nun eine Funktion habe, die mir aus vier Integern einen Vector
> erstellt und ich diesen Vector weiterverwenden will, wie bekomme ich
> ihn "aus der Methode raus"?

Nur am Rande: In C++ gibt es keine "Methoden". Es gibt nur Funktionen. 
Stroustrup verwendet das Wort "method" nur in Anführungszeichen und rät 
von der Verwendung ab.
Es gibt auch mehrere unterschiedliche Meinungen darüber, was genau damit 
in C++ überhaupt gemeint ist.

> Ich dachte da zuerst, der Methode einen Pointer zu übergeben, sodass
> die Methode diesen für die Ergebnisse benutzt. Ist
> dieser Ansatz richtig? Hat bei mir leider nicht geklappt ...

Was heißt "hat nicht geklappt"? Was ist passiert?

> Kann man in C++ eine Referenz auf ein Objekt einer Klasse zurückgeben?

Ja. Allerdings muß man dabei selbst darauf achten, daß das Objekt so 
lange gültig bleibt, wie die Referenz benutzt wird. Das bedeutet z.B. 
daß es grundsätzlich sinnlos ist, Referenzen auf lokale (non-static) 
Variablen zurückzugeben, da diese Variablen automatisch zerstört werden, 
bevor die Referenz überhaupt verwendet werden kann.

> Oder wie wird das allgemein gehandhabt?
>
> Java lässt grüßen ... ;)

Generell besteht bezüglich des Speicherhandling von Objekten ein großer 
Unterschied zwischen C++ und Java. C++ kennt drei Arten von Speicher, 
nämlich statisch, automatisch und dynamisch. Statische Variablen 
existieren praktisch bis zum Programmende (das sind globale Variablen, 
als static deklarierte Member-Variablen oder als static deklarierte 
lokale Variablen). Automatische Variablen werden beim Verlassen ihres 
Scope zerstört. Das sind lokale non-static-Variablen. Dynamische Objekte 
werden mit new angelegt und existieren solange, bis sie mit delete 
wieder zerstört werden.

von P. S. (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> jua schrieb:
>> Dass ein Compiler es möglicherweise optimieren kann, ist IMO kein guter
>> Grund, ineffizienten Code zu schreiben.
> Was ist bei dir ineffizient?

Ineffizient ist, wenn der Compiler die Kopieroperation doch macht, von 
der man dachte, er wuerde sie wegoptimieren.

> Letzten Endes, wenn mein dein Argument ins Extrem treibt, bedeutet es:
> Alles ausser Assembler ist Müll :-)

Jedes Argument, dass man in's Extrem treibt, wird absurd. Deswegen 
laesst man das, wenn man eine sinnvolle Diskussion fuehren will.

> Mach dir um Effizenz keine Sorgen. C++ Compiler sind viel besser als du
> glaubst.

Sie sind viel schlechter, als du glaubst. Und noch dazu ist das Wissen 
von einem Compiler auf den anderen nicht einfach uebertragbar. Noch 
nicht einmal von einer Version auf die andere. Schon deshalb ist es 
fahrlaessig, sich auf solche Eigenschaften zu verlassen.

> Schon so mancher C Trickser, der auf seiner Überlegenheit
> gepocht hat, hat sein blaues Wunder erlebt, als der C++ Compiler aus
> einem ordinärem, schön geschriebenen, kanonischen C++ Programm etwas
> erzeugt hat, was seine 'hoch-optimierte' C-Lösung alt aussehen hat
> lassen.

Stimmt. Deswegen wird der Umkehrschluss aber noch lange nicht zulaessig. 
Ich empfehle einfach mal etwas Praxis. Wer schon mal gezwungen war, dem 
Compiler genau auf die Finger zu schauen, kann nur die Haende ueber dem 
Kopf zusammenschlagen, was da manchmal bei rauskommt.

> Von "korrekter Fehlerbehandlung" versus "wieder einmal in C
> nicht freigegebenem Speicher" reden wir erst mal gar nicht.

Ach komm, immer der gleiche Spruch. Wer so viel Angst vor Speicherlecks 
hat, muss sich entweder mal auf den Hintern setzen und sein Programm in 
den Griff kriegen (was dann voellig ueberraschend auch allgemein die 
Programmqualitaet hebt), oder eine Sprache verwenden, die diesem 
persoenlichen Problem entgegenkommt.

> Wenn du Effizienz haben willst, denn leg dein Augenmerk auf Algorithmen.

Da gehoeren vernueftige Parameteruebergaben dazu.

von P. S. (Gast)


Lesenswert?

Rolf Magnus schrieb:
> jua schrieb:

> Daß eigentlich alle gängigen Compiler hier den effizienten Weg
> automatisch verwenden, ist ein guter Grund, einfacheren, lesbareren Code
> zu schreiben.

Einfach, lesbar und idiotentsicher: Den zu fuellenden Vector einfach 
uebergeben. Ob als Referenz oder Pointer ist mir schnuppe, auch wenn ich 
den Pointer vorziehe.

> Im Falle von Operatorüberladung, z.B. beim Operator+ geht's auch gar nicht 
anders.

Einfach, lesbar und Operatorueberladung passt nicht wirklich in einen 
Absatz.

von Klaus W. (mfgkw)


Lesenswert?

Mag alles sein. Das ändert aber nichts daran, daß man in
C++ Objekte prima zurückgeben kann.

von Klaus W. (mfgkw)


Lesenswert?

Peter Stegemann schrieb:
> Einfach, lesbar und Operatorueberladung passt nicht wirklich in einen
> Absatz.

Das kommt erstens drauf, ob man Operatorueberladung nutzt oder
missbraucht, und zweitens, ob man sie mag.
Es gibt nun wirklich Beispiele, wo sie die Lesbarkeit drastisch erhöhen.
(einstream << einwert gehört nicht unbedingt dazu)

von Εrnst B. (ernst)


Lesenswert?

Peter Stegemann schrieb:
> Einfach, lesbar und Operatorueberladung passt nicht wirklich in einen
> Absatz.

Warum? Was ist lesbarer?
1
c=a+b;
2
z=x+y;
oder
1
c=do_addition_for_datatype_abc(a,b);
2
z=add_vectors(x,y);

Klar, man kann mit Operator-Überladung viel Blödsinn anstellen, richtig 
angewendet kann man damit auch die Lesbarkeit ungemein erhöhen.

von jua (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Mach dir um Effizenz keine Sorgen. C++ Compiler sind viel besser als du
> glaubst.

Heh, das ist einer meiner Lieblingssprüche, direkt neben "Heutige 
Computer sind sowieso so schnell, dass [...]".

Compiler können vieles, man sollte sich aber im Allgemeinen nicht darauf 
verlassen. Das kann man tun bei simplen Compiler-Optimierungen -- 
constant folding, constant propagation, diese Art von Dingen. Bei 
komplexeren Konstrukten wird es jedoch unübersichtlich...

Und natürlich sind Algorithmen entscheident, aber auch eine effiziente 
Implementierung kann einen riesigen Unterschied machen. Einfaches 
Beispiel, folgende zwei Funktionen:
1
#define N 8192
2
3
int matrix[N][N];
4
int vector[N];
5
int result[N];
6
7
void MatrixVectorMult()
8
{
9
    for(int row = 0; row < N; row++)
10
        for(int col = 0; col < N; col++)
11
            result[row] = result[row] + matrix[row][col] * vector[col];
12
}
13
14
void MatrixVectorMult2()
15
{
16
    for(int col = 0; col < N; col++)
17
        for(int row = 0; row < N; row++)
18
            result[row] = result[row] + matrix[row][col] * vector[col];
19
}

Die Funktion Nr. 1 ist auf meinem Rechner mehr als 3 mal schneller als 
Funktion Nr. 2. Das Ergebnis ist das gleiche. Nun die Preisfrage: Warum 
ist Variante 1 so viel schneller und warum kann der Compiler es nicht 
optimieren? In der Antwort auf diese Frage erkennt man, warum die 
Implementierung nicht unwichtig ist...

von P. S. (Gast)


Lesenswert?

Klaus Wachtler schrieb:

> Das kommt erstens drauf, ob man Operatorueberladung nutzt oder
> missbraucht, und zweitens, ob man sie mag.
> Es gibt nun wirklich Beispiele, wo sie die Lesbarkeit drastisch erhöhen.
> (einstream << einwert gehört nicht unbedingt dazu)

Ernst hat ja schon ein Beispiel genannt. Und mit Verlaub, viele 
sinnvolle Anwendungen bleiben nicht mehr uebrig, die 
Missbrauchsmoeglichkeiten ueberwiegen bei weitem.

Wenn ich alle Gelegenheiten zusammenzaehle, bei denen ich in meinem 
Programmiererleben Operatorueberladung habe sinnvoll einsetzen koennen, 
dann komme ich auf: Einmal.

Frage mich nicht nach den Faellen, wo Operatorueberladung nur zu Chaos 
und schweren Fehlern gefuehrt hat, da kann ich nur sagen: Fast jedesmal. 
Wirklich zaehlen kann ich das nicht mehr.

von Klaus W. (mfgkw)


Lesenswert?

Peter Stegemann schrieb:
> Ernst hat ja schon ein Beispiel genannt. Und mit Verlaub, viele
> sinnvolle Anwendungen bleiben nicht mehr uebrig, die
> Missbrauchsmoeglichkeiten ueberwiegen bei weitem.

Es kommt halt drauf, was man gerade programmiert.
Wenn ich mir neue Datentypen schaffe, mit denen gerechnet werden
soll (z.B. die Festkommageschichte, die ich neulich mal machte),
ist Operatorueberladung einfach Gold wert.

Wenn es in 99% der Programm keinen Sinn macht, muß man es
halt bei diesen 99% nicht verwenden.

>
> Wenn ich alle Gelegenheiten zusammenzaehle, bei denen ich in meinem
> Programmiererleben Operatorueberladung habe sinnvoll einsetzen koennen,
> dann komme ich auf: Einmal.

Ein paar mehr hätte ich da schon zu bieten...

>
> Frage mich nicht nach den Faellen, wo Operatorueberladung nur zu Chaos
> und schweren Fehlern gefuehrt hat, da kann ich nur sagen: Fast jedesmal.
> Wirklich zaehlen kann ich das nicht mehr.

Mit dieser Begründung darfst du auch keine Zeiger nehmen :-)

---

Das alles ändert aber doch nichts daran, daß es legitim und sogar
explizit vorgesehen ist, in Funktionen und/oder Methoden Werte
zurückzugeben.

Ich verstehe nicht, wieso man das jetzt auf einmal verbieten soll.
Außer daß man es im Einzelfall "nicht mag" sehe ich irgendwie
kein echtes Argument dagegen.

von P. S. (Gast)


Lesenswert?

Diese Diskussion erinnert mich an eine alte Geschichte, noch aus dem 
Studium. Das muss so 14 Jahre her sein, da hat ein Mitstudent auch ein 
C++-Programm geschrieben, wo er alle Objekte als Kopien uebergeben hat. 
Wirklich ueberraschend war das nicht, da der Professor didaktisch eine 
Null war und C++ sehr abstrakt gelehrt hat. Das endete dann auch noch in 
anderen Katastrophen wie Endlosrekursionen (waeren C++-Methoden-Aufrufe 
wirklich Messages, wie es so schoen abstrakt erklaert wurde, waere das 
ja gegangen). Der Kollege hat sich auch gewundert, warum sein Programm 
so langsam ist.

Wer nun meint, das sei eine olle Kamelle und die Compiler seien heute ja 
schon viel weiter:

1) Wenn ich jedesmal, wenn mir jemand erklaert heute sei ja sowas kein 
Problem mehr, mich darauf einlasse und das ueberpruefe, tue ich nichts 
anderes mehr.

2) In der Praxis ist es ueberhaupt nichts Besonderes, auf so alte 
Compiler zu stossen.

3) Es gleich richtig zu machen, ist genauso einfach.

von P. S. (Gast)


Lesenswert?

Klaus Wachtler schrieb:
> Peter Stegemann schrieb:

>> Frage mich nicht nach den Faellen, wo Operatorueberladung nur zu Chaos
>> und schweren Fehlern gefuehrt hat, da kann ich nur sagen: Fast jedesmal.
>> Wirklich zaehlen kann ich das nicht mehr.
> Mit dieser Begründung darfst du auch keine Zeiger nehmen :-)

Doch. Sie sind ein grundlegender Sprachbestandteil, klar definiert und 
machen, was sie sollen - es sei denn, jemand ueberlaedt einen Operator. 
Dann reagiert Code, der aussieht wie jeder andere Code, ploetzlich 
anders.

> Das alles ändert aber doch nichts daran, daß es legitim und sogar
> explizit vorgesehen ist, in Funktionen und/oder Methoden Werte
> zurückzugeben.

Ohne wuerden viele Methoden ja wenig Sinn ergeben :-)

> Ich verstehe nicht, wieso man das jetzt auf einmal verbieten soll.

Wer sagt denn, dass es verboten werden soll? Aber andersrum muss man 
doch auch mal fragen duerfen: Hat die Sprache das jetzt unbedingt 
gebraucht? Denn C++ wird nach wie vor von wildgewordenen Gremien 
"verbessert".

> Außer daß man es im Einzelfall "nicht mag" sehe ich irgendwie
> kein echtes Argument dagegen.

Operatorueberladung ist ein maechtiges Schwert und fuehrt sehr leicht zu 
extrem unangenehmen Fehlerquellen. Und leider werden sie von vielen als 
tolle, harmlose Kosmetik angepriesen, die den Code huebscher macht und 
entsprechend hemmungslos eingesetzt. Und wenn man dann beruflich solchen 
Mist aufraeumen muss, dann geht es nicht mehr um "moegen" oder "nicht 
moegen" sondern um ein immer mehr um sich greifendes Aergernis.

von Klaus W. (mfgkw)


Lesenswert?

Peter Stegemann schrieb:
> Diese Diskussion erinnert mich an eine alte Geschichte, noch aus dem
> ...

Wie soll in dem Punkt ein Compiler weiter sein?
Man kann Parameter als Zeiger oder Referenzen oder Wert
übergeben; wenn man die falsche Wahl trifft, kann der Compiler
nichts dafür.

Aber was hat das jetzt mit der Rückgabe von Objekten zu tun? :-)

von Klaus W. (mfgkw)


Lesenswert?

Peter Stegemann schrieb:
> Dann reagiert Code, der aussieht wie jeder andere Code, ploetzlich
> anders.

Das ist aber eher ein Problem des Betrachters.
Wenn man mit + nur int- oder double-Addition assoziiert, hat
man Pech.
Hat man dagegen im Kopf, daß ein + halt ein Operatoraufruf ist,
sind die Folgen nicht überraschender als bei einer Funktion add().
Der sehe ich beim Aufruf auch nicht an, ob sie wirklich addiert
oder was ganz anderes macht.

Peter Stegemann schrieb:
> Operatorueberladung ist ein maechtiges Schwert und fuehrt sehr leicht zu
> extrem unangenehmen Fehlerquellen. Und leider werden sie von vielen als
> tolle, harmlose Kosmetik angepriesen, die den Code huebscher macht und
> entsprechend hemmungslos eingesetzt. Und wenn man dann beruflich solchen
> Mist aufraeumen muss, dann geht es nicht mehr um "moegen" oder "nicht
> moegen" sondern um ein immer mehr um sich greifendes Aergernis.

Aber das ist doch mit allen Möglichkeiten von C++ so.
Es gibt viele Leute, die sie nicht verstanden haben und
nur herumpfuschen.

Nur weil viele Deppen nicht mit scharfen Werkzeugen
umgehen können, will ich doch nicht mit der Nagelfeile einen
Motorblock fräsen.

von P. S. (Gast)


Lesenswert?

Klaus Wachtler schrieb:

> Wie soll in dem Punkt ein Compiler weiter sein?
> Man kann Parameter als Zeiger oder Referenzen oder Wert
> übergeben; wenn man die falsche Wahl trifft, kann der Compiler
> nichts dafür.
>
> Aber was hat das jetzt mit der Rückgabe von Objekten zu tun? :-)

Zitat: "Fazit: keine Angst davor, Objekte direkt aus einer Funktion 
heraus als Return Wert zu liefern. Compiler haben Methoden, wie sie auch 
diese Fälle schnell machen können."

von Klaus W. (mfgkw)


Lesenswert?

Da hast du Recht, die Aussage ist falsch.
Denn ich habe heute gelernt, daß es in C++ gar keine Methoden gibt :-))

von P. S. (Gast)


Lesenswert?

Klaus Wachtler schrieb:

> Das ist aber eher ein Problem des Betrachters.
> Wenn man mit + nur int- oder double-Addition assoziiert, hat
> man Pech.

Es geht nicht nur um + und -. So richtig Chaos kannst du mit ==, () und 
-> anrichten. Hat da der werte Leser auch Pech?

> Aber das ist doch mit allen Möglichkeiten von C++ so.
> Es gibt viele Leute, die sie nicht verstanden haben und
> nur herumpfuschen.

Deswegen muss man das aber nicht noch unterstuetzen und das als schick 
und easy propagieren. Du legst einem Kind doch auch kein Messer hin und 
sagst: "Guck mal, damit kann man total toll schnippeln, das musst du 
unbedingt immer dabei haben!" Und dieser leichtfertige Umgang ist eben 
ein trauriger Fakt.

> Nur weil viele Deppen nicht mit scharfen Werkzeugen
> umgehen können, will ich doch nicht mit der Nagelfeile einen
> Motorblock fräsen.

Ja, den Spruch habe ich schon oft gehoert. Das Resultat sind dann 
regelmaessig abgespacte Konstruktionen, bei denen die neuesten Patterns 
und die coolsten Sprachfeatures umgesetzt werden. Nur leider kann das 
sonst kein Schwein mehr lesen, geschweige denn warten.

Wenn du mich beeindrucken willst: KIS.

von Karl H. (kbuchegg)


Lesenswert?

Peter Stegemann schrieb:
> Diese Diskussion erinnert mich an eine alte Geschichte, noch aus dem
> Studium. Das muss so 14 Jahre her sein, da hat ein Mitstudent auch ein
> C++-Programm geschrieben, wo er alle Objekte als Kopien uebergeben hat.

Du vergleichst hier Äpfel mit Birnen.
Von Objekten in eine Funktion hineinübergeben war nicht die Rede.
Und da habe ich das Valuepassing auch nicht schön geredet.

Es geht um Return Werte!

Argument Passig ist eine andere Geschichte

* Handelt es sich um einen skalaren Typ, wie int, long ...

   ja: Übergib per Value

Nein: Brauchst du die Möglichkeit, der Funktion anzeigen zu können:
   Ich hab nichts für dich?

   ja: Übergib einen Pointer

Nein: Muss die Funktion den Wert beim Aufrufer verändern können?

   ja: Übergib eine Referenz

Nein: Übergib eine const Referenz

Mit diesem Entscheidungsbaum hast du alles was du brauchst, in der 
effizientesten Art.


Operator Overloadiung:
Nur weil du keine Klassen gefunden hast, bei denen Operator Overloadding 
Sinn macht, heist das ja noch lange nicht, dass andere so etwas nicht 
brauchen können.
Vektoren, Matrizen, Sowohl 2D als auch 3D, Operationen mit Geometrien 
(Boolsche Operationen auf Flächen/Körpern), ...
Was denkst du, wie wunderbar schön, kurz, übersichtlich und nicht 
zuletzt fehlerunanfällig sich das in CAD-Code benutzen lässt.
Dagegen sind die alten C-Kamellen mit Unmengen an Funktionsaufrufen 
reinster Unfug dagegen.
1
class Vector2D
2
{
3
public:
4
  Vector2D( double x = 0.0; double y = 0.0 )
5
  : x_( x ),
6
    y_( y )
7
  {}
8
9
  double x() const    { return x_; }
10
  double y() const    { return y_; }
11
12
  Vector2D operator+( const Vector2D& rhs ) const { return Vector2D( x_ + rhs.x(), y_ + rhs.y() );
13
  Vector2D operator-( const Vector2D& rhs ) const { return Vector2D( x_ - rhs.x(), y_ - rhs.y() );
14
15
  bool operator==( const Vector2D& rhs ) const { return 'dein Kriterium für gleich'; }
16
   
17
private:
18
  double x_;
19
  double y_;
20
};
21
22
23
24
int main()
25
{
26
  Vector2D a, b( 8 ), d(5, 2);
27
  Vector2D c = a + b;
28
29
  printf( "Value %lf\n", (c + a).y() );
30
}

Herz was willst du mehr. Und ja, ich verlass mich darauf, dass im 
letzten Fall der Compiler die komplette Berechnung von x wegoptimiert. 
Und ja, ich verlasse mich darauf, dass der Compiler bei der 
Initialisierung von c das temporäre Objekt wegoptimiert. (Und seit 10 
Jahren hab ich keinen Compiler mehr gesehen, der es nicht getan hätte. 
Davor hab ich nicht im Assemblercode nachgesehen)

C++, wenn man die Sprache richtig benutzt, ist auf die Fähigkeiten des 
Optimizers angewiesen. Die Compilerbauer wissen das und haben hart daran 
gearbeitet. Es wäre dumm, die nicht zu benutzen, wenn man sich dadurch 
das Leben leichter machen kann.

Und ja, man kann sich mit Operator Overloading selbst ein Bein stellen. 
Genauso wie man sich ein Bein stellen kann, wenn man Unmengen an 
Conversion Operatoren schreibt. Und? Man kann sich auch selbst mit einem 
Revolver ins Bein schiessen.
Niemand sagt, dass man nach 2 Tagen C++ Grundkurs perfekt ist. Dazu gibt 
es Lernphasen, in denen man lernt was man tun darf, tun soll und was man 
besser nicht tut.

von Karl H. (kbuchegg)


Lesenswert?

Peter Stegemann schrieb:

> Wenn du mich beeindrucken willst: KIS.

Yep.
Keep it simple.
Aber dort wo eine Klasse verwendet wird! Das soll so simpel wie möglich 
sein. Die Klasse darf (und soll auch) ruhig ein wenig Aufwand treiben um 
das zu ermöglichen.

Wenn du mich beeindrucken willst: Dann schreib Klassen, die auf sich 
selbst aufpassen und die verhindern, dass man sie missbräuchlich 
verwenden kann.

von Karl H. (kbuchegg)


Lesenswert?

Peter Stegemann schrieb:

> Es geht nicht nur um + und -. So richtig Chaos kannst du mit ==, () und
> -> anrichten. Hat da der werte Leser auch Pech?

Du hast den Komma Operator vergessen :-)

Aber im Ernst: Nur weil es ein paar Operatoren gibt, die man besser 
nicht überlädt, heißt das noch lange nicht, das Operator Overloading als 
Ganzes Teufelswerk ist.

> Deswegen muss man das aber nicht noch unterstuetzen und das als schick
> und easy propagieren. Du legst einem Kind doch auch kein Messer hin und
> sagst: "Guck mal, damit kann man total toll schnippeln, das musst du
> unbedingt immer dabei haben!" Und dieser leichtfertige Umgang ist eben
> ein trauriger Fakt.

Fakt ist, genauso wie wir es hier in Form von C jeden Tag sehen, dass 
viele Leute C++ programmieren, ohne die Sprache zu kennen. Niemand 
bestreitet dass es auch in C++ Fallen gibt. Das bedeutet aber nicht, 
dass man grundsätzlich nicht in C++ programmieren kann. Und zwar nicht 
auf die Art 'C mit Klassen', sondern so wie sich das die Erfinder 
vorgestellt haben: In einer objektorientierten Art und Weise.

von Karl H. (kbuchegg)


Lesenswert?

Peter Stegemann schrieb:

>> Von "korrekter Fehlerbehandlung" versus "wieder einmal in C
>> nicht freigegebenem Speicher" reden wir erst mal gar nicht.
>
> Ach komm, immer der gleiche Spruch.

Weil er leider immer noch ein Thema ist.
Es tut mir leid dir das sagen zu müssen, aber in den meisten hinreichend 
großen C Programmen sind nun mal Speicherlecks. Solange es sich nur um 
Lecks handelt geht es ja noch. Viel schlimmer ist es, wenn sich mal 
wieder einer den Speicher niederbügelt.

Und mehr als einmal ist die Ursache dafür: Keine Organisation im Code 
und wildes C Gehacke.

> Wer so viel Angst vor Speicherlecks
> hat, muss sich entweder mal auf den Hintern setzen und sein Programm in
> den Griff kriegen (was dann voellig ueberraschend auch allgemein die
> Programmqualitaet hebt), oder eine Sprache verwenden, die diesem
> persoenlichen Problem entgegenkommt.

Genau: zb C++ mit RAII Idiom.

>> Wenn du Effizienz haben willst, denn leg dein Augenmerk auf Algorithmen.
>
> Da gehoeren vernueftige Parameteruebergaben dazu.

Sorry.
Aber mit dieser Aussage bist du bei mir unten durch.

von P. S. (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Peter Stegemann schrieb:
>> Diese Diskussion erinnert mich an eine alte Geschichte, noch aus dem
>> Studium. Das muss so 14 Jahre her sein, da hat ein Mitstudent auch ein
>> C++-Programm geschrieben, wo er alle Objekte als Kopien uebergeben hat.
> Du vergleichst hier Äpfel mit Birnen.

Du greifst dir aus meinen ganzen Postings einen Satz raus, den man 
einseitig interpretieren kann und reduzierst alles, was ich geschrieben 
habe, darauf.

> Von Objekten in eine Funktion hineinübergeben war nicht die Rede.
> Und da habe ich das Valuepassing auch nicht schön geredet.
>
> Es geht um Return Werte!

Das ist auch eine Uebergabe, eben von der aufgerufenen Funktion an den 
Aufrufer.

> Argument Passig ist eine andere Geschichte

Jetzt erklaere dem Laien mal, warum die allgemeine Aussage von oben 
"Mach dir um Effizenz keine Sorgen. C++ Compiler sind viel besser als du 
glaubst.", hier ploetzlich nicht gilt.

> Operator Overloadiung:
> Nur weil du keine Klassen gefunden hast, bei denen Operator Overloadding
> Sinn macht, heist das ja noch lange nicht, dass andere so etwas nicht
> brauchen können.

Du wiederholst hier nur, was Klaus schon geschrieben und ich schon 
beantwortet habe.

> C++, wenn man die Sprache richtig benutzt, ist auf die Fähigkeiten des
> Optimizers angewiesen. Die Compilerbauer wissen das und haben hart daran
> gearbeitet. Es wäre dumm, die nicht zu benutzen, wenn man sich dadurch
> das Leben leichter machen kann.

Sorry, aber solche Aussagen sind voellig praxisfern. Das solltest du mit 
deiner Berufserfahrung eigentlich wissen. Bin ich dumm, wenn ich in 
einem zig Jahre alten Grossprojekt den Compiler nicht austausche? Wenn 
ich meinen Code ohne Mehraufwand so gestalte, dass er nicht vom letzten 
Optimizertrick abhaengt? Oder bin ich nicht eher dumm, wenn ich mein 
Gehirn abschalte und jede Feature der Sprache einsetze, nur weil es da 
ist?

von P. S. (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Peter Stegemann schrieb:

>> Ach komm, immer der gleiche Spruch.
> Weil er leider immer noch ein Thema ist.
> Es tut mir leid dir das sagen zu müssen, aber in den meisten hinreichend
> großen C Programmen sind nun mal Speicherlecks. Solange es sich nur um
> Lecks handelt geht es ja noch. Viel schlimmer ist es, wenn sich mal
> wieder einer den Speicher niederbügelt.

Sprich bitte nur fuer deine Projekte. Im professionellen Umfeld gibt es 
zur Not auch professionelle Tools. Und wer sich mit den damit 
erreichbaren Ergebnissen nicht zufrieden geben kann: Es gibt Sprachen, 
die diese Probleme wesentlich besser loesen, als jeder C++-Trick.

> Und mehr als einmal ist die Ursache dafür: Keine Organisation im Code
> und wildes C Gehacke.

In diesen Faellen sind Speicherlecks nicht das Problem, sondern nur ein 
Indikator. Wenn du die Speicherlecks trocken legst, ist die Applikation 
immer noch kaputt. Du doktorst also an den Symptomen rum, statt die 
Ursachen anzugehen.

>>> Wenn du Effizienz haben willst, denn leg dein Augenmerk auf Algorithmen.
>> Da gehoeren vernueftige Parameteruebergaben dazu.
> Sorry.
> Aber mit dieser Aussage bist du bei mir unten durch.

Kein Argument, das mich ueberzeugt.

von Karl H. (kbuchegg)


Lesenswert?

Peter Stegemann schrieb:

>> Argument Passig ist eine andere Geschichte
>
> Jetzt erklaere dem Laien mal, warum die allgemeine Aussage von oben
> "Mach dir um Effizenz keine Sorgen. C++ Compiler sind viel besser als du
> glaubst.", hier ploetzlich nicht gilt.

Das war keine allgemeine Aussage.
Das war eine Aussage im Kontext von Return Wert passing.
Der ganze Thread hat sich anfangs darum gedreht. Mein ganzes Posting hat 
sich darum gedreht:
Return Wert Passing und was der Compiler tun kann und tun darf, damit 
man dort keinen Penalty zahlen muss.

Du bist derjenige, der den Kontext des Threads davon weg geholt hat!


> Oder bin in ich nicht eher dumm, wenn ich mein
> Gehirn abschalte und jede Feature der Sprache einsetze, nur weil es da
> ist?

Dinke für die Blumen.
Gute Nacht.

Schreib deine C Programme von mir aus mit 'C mit Klassen'. Aber lass 
andere C++ programmieren. OK?

von P. S. (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:

> Du bist derjenige, der den Kontext des Threads davon weg geholt hat!

Mach mal den Computer aus, rege dich ein wenig ab und lies morgen 
nochmal in Ruhe nach, wie sich der Thread entwickelt hat und warum.

> Dinke für die Blumen.

Vergiss nicht, wer damit angefangen hat, anderen Dummheit zu 
unterstellen.

von Karl H. (kbuchegg)


Lesenswert?

Peter Stegemann schrieb:
> Karl heinz Buchegger schrieb:
>
>> Du bist derjenige, der den Kontext des Threads davon weg geholt hat!
>
> Mach mal den Computer aus, rege dich ein wenig ab und lies morgen
> nochmal in Ruhe nach, wie sich der Thread entwickelt hat und warum.

Und in der Zwischenzeit kannst du ja mal darüber nachdenken, wie 
sinnvoll es ist, Sprachfeatures zu verdammen und die generelle 
Empfehlungen 'alles ist ein Pointer' und 'Return by Pointer Passing' ist 
das einzig Wahre, nur weil du in der durchaus bedauernswerten Situation 
bist, himmelalten Code auf einem noch älteren Compiler warten zu müssen.
Der Rest der C++ Gemeinde benutzt ganz einfach C++ so wie es gedacht ist 
und erfreut sich daran, dass sie neuere Compiler benutzen können, für 
die diese Optimierungen nicht der Rede wert sind.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.