Forum: Compiler & IDEs Verständnis c++ AVR Konstruktoren und co.


von Christian A. (ferrice)


Lesenswert?

Hallo!

Gibt es irgendwo ein Tutorial wo die grundlegenden Unterschiede zwischen 
der normalen c++ programmierung und der Implementierung am AVR dargelegt 
sind?

Jetzt im speziellen beim Konstruktor: Habe schon zwei schreibweisen 
gesehen, die mir nicht ganz klar sind.

ClassA hat einen Konstruktur welcher einen u8 entgegen nimmt
1
ClassA a = ClassA(2);    oder
2
ClassA a(2);

Was ist der Unterschied bei diesen Anweisungen?
Die Anlegung einer Variable (a) dient nur um auf die statischen Elemente 
zuzugreifen oder?

lg

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Christian J. schrieb:

> Was ist der Unterschied bei diesen Anweisungen?

Die Schreibweise.

> Die Anlegung einer Variable (a) dient nur um auf die statischen Elemente
> zuzugreifen oder?

Nein.

a ist eine Instanz der Klasse.

Das alles hat mit AVR oder nicht AVR nichts zu tun.

von Christian A. (ferrice)


Lesenswert?

Danke erstmal...

Also ist zwischen den zwei Schreibweisen kein Unterschied?
Wie werden diese Objekte am µC verwaltet?

Wenn ich jetzt zwei Instanzen erzeuge und jede Instanz ihre eigenen 
Eigenschaften hat, wo werden wiese abgelegt?
Wenn ich jetzt eine Methode der beiden Instanzen aufrufe... Handelt es 
sich dann um eine statische Funktion die für beide Instanzen gleich ist 
oder?

Gibt es zu dem ganzen Thema eine gute Literatur, wo man das nachlesen 
kann?

LG

von apr (Gast)


Lesenswert?

Christian J. schrieb:
> Gibt es zu dem ganzen Thema eine gute Literatur, wo man das nachlesen
> kann?

Ein C++ Buch.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

apr schrieb:
> Christian J. schrieb:
>> Gibt es zu dem ganzen Thema eine gute Literatur, wo man das nachlesen
>> kann?
>
> Ein C++ Buch.

Sehe ich auch so.  Bis hierhin sind das alles völlig grundlegende
C++-Fragen.

von Carl D. (jcw2)


Lesenswert?

Christian J. schrieb:
>
> ClassA hat einen Konstruktur welcher einen u8 entgegen nimmt
>
1
ClassA a = ClassA(2);    oder
2
> ClassA a(2);
3
>

Grundsätzlich sollte man "dynamisches" vermeiden, was C++ nicht immer 
offensichtlich macht.
1.Variante sollte ein Instanz a erzeugen (via Default Konstruktor), dann 
eine dynamische Instanz, die durch Aufruf des =Operators auf a "kopiert" 
wird.
2.Variante erzeugt a über den Konstruktor, der ein uint8_t erwartet.

Allerdings wird GCC im Fall 1 warscheinlich entdecken, daß das im 
Ergebnis mit Fall 2 übereinstimmt und den Optimizer-Hobel ansetzen. Es 
scheint dann so,als wäre das identisch.
Für C++ auf AVR ist es aber gut, wenn man den Unterschied versteht.

von apr (Gast)


Lesenswert?

Carl Drexler schrieb:
> Grundsätzlich sollte man "dynamisches" vermeiden, was C++ nicht immer
> offensichtlich macht.
Da ist nichts dynamisches.

> 1.Variante sollte ein Instanz a erzeugen (via Default Konstruktor), dann
> eine dynamische Instanz, die durch Aufruf des =Operators auf a "kopiert"
> wird.
Nein.

> 2.Variante erzeugt a über den Konstruktor, der ein uint8_t erwartet.
Die Varianten sind gleich.

> Allerdings wird GCC im Fall 1 warscheinlich entdecken, daß das im
> Ergebnis mit Fall 2 übereinstimmt und den Optimizer-Hobel ansetzen. Es
> scheint dann so,als wäre das identisch.
> Für C++ auf AVR ist es aber gut, wenn man den Unterschied versteht.
Nein. Es gibt hier keinen Unterschied. Das sind alles initializer. Da 
wird nichts assigned.

von Yodaminator (Gast)


Lesenswert?

apr schrieb:
>> 1.Variante sollte ein Instanz a erzeugen (via Default Konstruktor), dann
>> eine dynamische Instanz, die durch Aufruf des =Operators auf a "kopiert"
>> wird.
> Nein.
und wieso nicht? ich sehe das genauso wie christian...

>
>> 2.Variante erzeugt a über den Konstruktor, der ein uint8_t erwartet.
> Die Varianten sind gleich.
im endeffekt durch den optimizer ja, rein programmier-logisch nicht

von Rolf M. (rmagnus)


Lesenswert?

apr schrieb:
>> Grundsätzlich sollte man "dynamisches" vermeiden, was C++ nicht immer
>> offensichtlich macht.
> Da ist nichts dynamisches.
>
>> 1.Variante sollte ein Instanz a erzeugen (via Default Konstruktor), dann
>> eine dynamische Instanz, die durch Aufruf des =Operators auf a "kopiert"
>> wird.
> Nein.
>> 2.Variante erzeugt a über den Konstruktor, der ein uint8_t erwartet.
> Die Varianten sind gleich.

Auch nein.

>> Allerdings wird GCC im Fall 1 warscheinlich entdecken, daß das im
>> Ergebnis mit Fall 2 übereinstimmt und den Optimizer-Hobel ansetzen. Es
>> scheint dann so,als wäre das identisch.
>> Für C++ auf AVR ist es aber gut, wenn man den Unterschied versteht.
> Nein. Es gibt hier keinen Unterschied.

Doch, den gibt es. Fall 1 erzeugt ein temporäres Objekt vom Typ ClassA 
und erzeugt dann a per Copy-Kontruktor daraus. Fall 2 erzeugt a direkt.
Dem Compiler ist es allerdings gestattet, diese Copy-Konstruktion 
wegzuoptimieren. Wenn der Copy-Konstruktor nicht aufrufbar ist, bekommst 
du aber dennoch eine Fehlermeldung.

> Das sind alles initializer. Da wird nichts assigned.

Das ist richtig.

von Rolf M. (rmagnus)


Lesenswert?

Yodaminator schrieb:
> apr schrieb:
>>> 1.Variante sollte ein Instanz a erzeugen (via Default Konstruktor),
>>> dann eine dynamische Instanz, die durch Aufruf des =Operators auf a
>>> "kopiert" wird.
>> Nein.
> und wieso nicht?

Weil da nirgends eine Zuweisung vorkommt.
1
Typ Name = Wert;
Das ist keine Zuweisung, sondern eine Definition einer Variablen mit 
Initialisierung. Es wird kein Operator aufgerufen, sondern der 
Konstruktor.
1
Name = Wert;
Das ist eine Zuweisung. Hier wird der operator = aufgerufen.

von Paul (Gast)


Lesenswert?

Für genau diese Fragen empfehle ich:
"Effective C++" von Scott Meyers

In dem Buch wird genau erklärt was genau in derartigen Fällen vor sich 
geht.

von Karl H. (kbuchegg)


Lesenswert?

apr schrieb:

> Nein. Es gibt hier keinen Unterschied. Das sind alles initializer. Da
> wird nichts assigned.

Man kann das ruhig verallgemeinern:

Wird ein Objekt definiert

   myClass b;

dann ist das eine Objekterzeugung. Die Erzeugung eines neuen Objektes 
impliziert aber IMMER einen Aufruf eines Konstruktors (und zwar für 
dieses Objekt von nur EINEM Konstruktor und sonst nichts anderes). 
Immer. Eine eventuell angegebene Initialisierung, egal wie sie aussieht, 
kann nur noch aus den vorhandenen Konstruktoren eine Auswahl treffen - 
aber der Aufruf eines Konstruktors ist unabdingbar. Ein op= hat an 
dieser Stelle überhaupt keine Daseinsberechtigung.

In C++ muss man ganz klar zwischen Initialisierung und Zuweisung 
unterscheiden.
  Initialisierung  ... Aufruf eines entsprechenden Konstruktors, das
                       Objekt existierte vorher noch nicht
  Zuweisung        ... Aufruf des op=. Das Objekt existierte vorher
                       bereits, d.h. der op= muss sich auch um das
                       'Zerstören' des alten Objektinhaltes kümmern,
                       sofern es da etwas zu tun gibt.

Nicht jedes = ist eine Zuweisung. Bei der Erzeugung eines neuen Objektes 
kann es keine Zuweisung geben, sondern das ist immer ein 
Konstruktoraufruf und nicht mehr.

von Karl H. (kbuchegg)


Lesenswert?

Carl Drexler schrieb:

> Allerdings wird GCC im Fall 1 warscheinlich entdecken, daß das im
> Ergebnis mit Fall 2 übereinstimmt und den Optimizer-Hobel ansetzen. Es
> scheint dann so,als wäre das identisch.

Nicht nur das.

Wir reden hier von der sog. 'Named Return Value Optimization' bzw. in 
neueren Standards die 'copy elision'. Jeder C++ Compiler, der auch nur 
ansatzweise ernst genommen werden will, muss diese Optimierung 
beherrschen.
Diese Optimierung ist für C++ so wichtig wie ein Schluck Wasser für 
einen Ertrinkenden. Der Compiler würde ansonsten den Code mit der 
Erzeugung von temporären Objekten regelrecht überfluten - speziell bei 
Templates kommt diese Situation oft vor.
Immerhin wichtig genug, dass sie die einzige Optimierung ist, die im C++ 
Standard beschrieben und für die eine AUSNAHME von der 'As-If' Regel 
gemacht wird. D.h. der Compiler muss nicht den Code des Copy 
Construktors analysieren um festzustellen, ob dieser Nebeneffekte hat, 
die über das reine Erzeugen einer Objektkopie hinausgehen. Sobald ein 
Copy-Constructor im Spiel ist, darf der Compiler diese Optimierung 
anwenden (und noch ein paar Nebenbedingungen technischer Natur), selbst 
dann WENN der vom Programmierer geschrieben CCtor Nebeneffekte aufweist, 
die durch die Optimierung wegfallen.
Daraus folgt: Es ist nicht schlau, Funktionalität in den CCtor 
reinzulegen, die nichts mit dem Erzeugen einer Kopie zu tun hat. Wer 
also seine Lichtorgel so aufbaut, dass bei jedem Aufruf des CCtor eine 
Lampe umgeschaltet wird und er die Logik so aufbaut, dass die Lichtorgel 
aus einem geordneten kopieren von Objekten besteht - der hat mit 
Zitronen gehandelt.

von Karl H. (kbuchegg)


Lesenswert?

Paul schrieb:
> Für genau diese Fragen empfehle ich:
> "Effective C++" von Scott Meyers

Jep.

Ein grundlegendes C++ Buch
Dann den Meyers
Und hinten nach noch "More effective C++" vom selben Autor
Und noch was grundlegendes über die STL (Nicolai Josuttis wurde früher 
dafür immer gerne empfohlen)

dann hat man alles in seiner Bibliothek stehen, so dass einen so schnell 
nichts mehr aus der Bahn wirft. Die Bücher aber auch lesen/durcharbeiten 
und nicht nur ins Regal stellen. Speziell das grundlegende C++ Buch ist 
für den Einstieg  wichtig!

Wer dann immer noch nicht genug hat, der möge sich Literatur von 'Herb 
Sutter' zulegen. Hochgradig empfohlen wenn es um die (oftmals gar nicht 
so kleinen) Kleinigkeiten in der Sprache geht.

Für Ansätze und Ideen zur Objektorientierten Programmierung gäbe es dann 
noch die sog. 'Gang of Four' - GOF - 
http://en.wikipedia.org/wiki/Design_Patterns_(book)

(Bitte im Link die ) ergänzen - Fehler in der Forensoftware)


Wer sich in C++ fit genug fühlt und wirklich was lernen will, kann sich 
ja mal durch Herb Sutters - "Guru of the Week" durcharbeiten. Herb hat 
damit seit 1997 Millionen C++ Programmierern weltweit gezeigt, was C++ 
ist und wie man es korrekt verwendet um zum Profi zu werden. C++ 
Kentnisse werden vorausgesetzt - am Anfang weniger, zum Schluss schon 
mehr. Herb hatte die jeweilige GotW Frage in einer Newsgroup gestellt, 
dann lies er die Leser eine Woche lang diskutieren bis er dann seine 
Sicht der Dinge veröffentlichte. Und genau so sollte man das auch 
halten: Frage lesen - darüber nachdenken - Herbs Antwort dazu lesen.
http://www.gotw.ca/gotw/index.htm
Unten, beim ersten Eintrag anfangen!
Zb. behandelt GotW #1 genau den Fall der Initialisierung
http://www.gotw.ca/gotw/001.htm

von Simon H. (simi)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Und hinten nach noch "More effective C++" vom selben Autor

Mit dem wunderschönen deutschen Titel: "Mehr effektiv C++ programmieren" 
:-)

Aber man muss es eh auf Englisch lesen, schon alleine wegen dem coolen 
Schreibstil des Autors. :-)

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.