Maschienencode konvertierung
-
Ich seh den Zusammenhang nicht ganz. Inwiefern würde eine Definition (nicht Deklaration) von tmp im übergeordneten scope (also der main-Funktion) das RAII-Idiom verletzen?
Die STL macht gebrauch von der RAII-Technik - beim file-stream-template wird eben im Destruktor close() aufgerufen. Dann macht es allerdings wenig Sinn, wenn ich die Lebensdauer eines filestream-Objekts unnötig verlänger - im schlimmsten Fall leg ich es global an.
Also versucht man Objekte möglichst lokal zu halten und genau das geschieht hier doch.
-
struct Foo { Foo() Foo(std::istream &); std::istream & operator >> (std::istream &); }; int main() { Foo foo; // Initialisierung { std::cin >> foo; // Zuweisung } Foo bar(std::cin); // Initialisierung }Oder wo ist mein Denkfehler?
-
std::cin ist ein Objekt, kein Typ.
{ std::cin >> foo; // Zuweisung }Hier wird also kein Konstruktor oder Destruktor aufgerufen, folglich findet kein RAII statt.
-
Genau das steht doch dort?
-
Dann schreib doch bitte was dein Beispiel zeigen sollte. So wie du es gemacht hast, macht die Einführung eines weiteren Scopes natürlich keinen Sinn...
-
Es geht ja auch gar nicht um den Scope, sondern um RAII. Sorry wenn dich das verwirrt hat.
-
Paul Müller schrieb:
Es geht ja auch gar nicht um den Scope, sondern um RAII. Sorry wenn dich das verwirrt hat.
Ich sehe auch nicht, was das mit RAII zu tun haben soll. Und die Kommentare helfen nicht. Außerdem compiliert das nicht einmal.
-
Es geht ja auch gar nicht um den Scope, sondern um RAII.
Dein Beispiel hat nur, wie ich erklärt habe, nichts mit RAII zu tun.
RAII ist doch ganz einfach: Im Konstruktor fordere ich Ressourcen an (z.B. mit
new) und im Destruktoren gebe ich die Ressourcen wieder frei (z.B. mitdelete). Da die Destruktoren in C++ deterministisch sind, kann man sicher sein, dass sobald ein Objekt den Scope verlässt, der Destruktor aufgerufen wird und dadurch die Ressourcen freigegeben werden. Nur so kann man dann auch richtige Exceptionsicherheit bekommen.Zur Benutzung von std::fstream::close():
Diese macht nur Sinn, wenn man das Objekt für eine andere Datei wiederverwenden möchte, statt ein neues dafür anzulegen. In so einem Fall muss vorher close() aufgerufen werden, da sonst open() fehlschlägt.
-
So als kurz gesagt ich kann das ganze besser so machen ?
Beispiel 1:
Funktioniert
#include <iostream> #include <fstream> using namespace std; int main() { char save[200] ; unsigned char var; { ofstream file ( "exit.bin" ); file << "\x90"; } // file handle ist geschlossen { ifstream f2 ( "exit.bin" ); f2 >>save; } // f2 handle ist geschlossen var=save[0]; cout<<var<<endl; cout<< hex << static_cast<int>(var); system("PAUSE"); }Beispiel 2:
Ausgabe:
É
90Drücken Sie eine beliebige Taste . . .Funktioniert NICHT die Ausgabe ist falsch !
#include <iostream> #include <fstream> using namespace std; int main() { char save[200] ; unsigned char var; ofstream file ( "exit.bin" ); file << "\x90"; ifstream f2 ( "exit.bin" ); f2 >>save; var=save[0]; cout<<var<<endl; cout<< hex << static_cast<int>(var); system("PAUSE"); }Ausgabe:
0 Drücken Sie eine beliebige Taste . . .
Beispiel 3:
Funktioniert
#include <iostream> #include <fstream> using namespace std; int main() { char save[200] ; unsigned char var; ofstream file ( "exit.bin" ); file << "\x90"; file.close(); ifstream f2 ( "exit.bin" ); f2 >>save; f2.close(); var=save[0]; cout<<var<<endl; cout<< hex << static_cast<int>(var); system("PAUSE"); }Ausgabe:
É
90Drücken Sie eine beliebige Taste . . .
-
Weil du von der File in einen char* einliest, du musst in einen unsigned char einlesen -.-
-
Was ein ctor/dtor ist und wann sie gerufen werden, weiß ich. Ich weiß auch, ohne den Fachbegriff dafür zu wissen, was ich damit anstellen kann. Da bin ich mal so überheblich zu behaupten, man kann auch problemlos selbst drauf kommen. Was mich aber an Resource Acquisition Is Initialization gestört hat, ist dieses Acquisition Is Initialization. Das findet ja nicht statt, wenn ich eine undefinierte Variable hab. Im Gegenzug ist mein Objekt schon initialisiert, wenn ich ein komplexes Gebilde mit ctor habe und erst danach den eigentlichen Inhalt über einen Stream erhalte. In beiden Fällen kann also nicht die Rede von Ressourcenanforderung bei Initialisierung die Rede sein. Andrerseits bleibt auch offen, was genau mit Ressourcen gemeint ist? Der Laie (ich) würde jetzt an die paar Bytes auf den Stack denken. Weil darauf stoßen einem eigentlich alle konventionellen Beispiele zu RAII. Meist bekommt man gezeigt, dass man die Variablen anlegen soll, erst wenn man sie verwendet und das ist es dann. Das deckt sich aber wie geschrieben nicht 100%ig mit der Anforderung, die ich zum Beispiel bei Streams hab, dass das Objekt vorher vorhanden sein muss. Wenn man nach der englischen Wikipedia geht scheint es aber ein alleiniges ctor/dtor Problem zu sein, was dann auch mit eurer Erläuterung sich voll decken würde.
-
Da hast du einiges falsch verstanden.
Paul Müller schrieb:
Das findet ja nicht statt, wenn ich eine undefinierte Variable hab. Im Gegenzug ist mein Objekt schon initialisiert, wenn ich ein komplexes Gebilde mit ctor habe und erst danach den eigentlichen Inhalt über einen Stream erhalte.
Nachträgliche Wertänderung ist keine Initialisierung. Das Objekt wurde hat seine Ressourcen geholt (=Speicher reserviert, Dateien geöffnet, was auch immer) und ist danach initialisiert (d.h. betriebsfertig).
Andrerseits bleibt auch offen, was genau mit Ressourcen gemeint ist? Der Laie (ich) würde jetzt an die paar Bytes auf den Stack denken.
Alle begrenzten Mittel die dein Objekt in irgendeiner Art und Weise benutzt. Meistens Speicher. Aber in der Regel meint man damit Heapspeicher, weil Stackspeicher ohnehin schon automatisch ist und man die gleiche Funktionalität auch für andere ressourcen haben will.
Weil darauf stoßen einem eigentlich alle konventionellen Beispiele zu RAII.
Dann sind das schlechte Beispiele. Welche sind das?
Meist bekommt man gezeigt, dass man die Variablen anlegen soll, erst wenn man sie verwendet und das ist es dann.
Das ist dann die Benutzung. Halte die Objekte so lokal wie möglich, damit sie ihre Ressourcen zeitig wieder frei geben.
Das deckt sich aber wie geschrieben nicht 100%ig mit der Anforderung, die ich zum Beispiel bei Streams hab, dass das Objekt vorher vorhanden sein muss.
Nachträgliche Wertänderung ist keine Initialisierung. Das Objekt ist initialisiert, wenn es benutzbar ist. D.h., wenn man sich an das Prinzip hält, nachdem der Konstruktor durchgelaufen ist.
P.S.: War jetzt vielleicht ein bisschen verwirrend, weil ich nur stückchenweise auf deinen Text eingegangen bin und dadurch kein zusammenhängender Antworttext zustande gekommen ist. Guck dir unbedingt mal ein paar gute Erklärungen zu RAII an und bei Unklarheiten frag nach. Bei deinem Streambeispiel weiß ich immer noch nicht so genau, was du damit überhaupt zeigen willst.
-
SeppJ schrieb:
Guck dir unbedingt mal ein paar gute Erklärungen zu RAII an und bei Unklarheiten frag nach.