Klasse in sich selber Initialisieren/Instanzieren alá System::String?
-
achaj ich weis warum ich gcnbew nicht brauche, weil halt die daten bei string konform sind wodurch die auto. initiallisierung der variable problemlos erfolgen kann.
hmm... ich hätte jetzt getippt das "string" nen keyword vom compiler is und das der Compiler es von alleine kapiert
probier doch ma
String ^str = gcnew String(); //hab das blöde gefühl als hätte ich gcnew falsch geschrieben^^(MFC,C# only, sry)
da haste dann dein gcnew
-
ich geb mir die kugel schreib ich den so mies^^? also nochmal ich will das verhalten von System::String bei der initialisierung nachbauen für eine eigene klasse. und nein der compiler kann es eben nicht immer wissen.
Bsp1:
[GLOBAL]
char *str1;
System::String *str2;[irgendwo im prog lokal]
str1 = "huhu"; // fehler ist ja klar speicher wurde nie reserviert
str2 = "huhu"; // alles in ordnung str2 wird automatisch initialisiertin diesem fall kann der compiler doch garnicht wissen ob wirklich str2 mit "huhu" initialisiert wird, oder ich steh total auf dem schlauch. Der Compiler weis es nur in diesem fall.
Bsp2:
[irgendwo im prog]
char *str1 = "huhu"; //ok weil direkt initialisiert compiler kann sich zu 100% sicher sein
System::String *str2 = "huhu"; // gleicher fall, hier besteht die 100%ige sicherheitund mich interessiert das verhalten von System::String aus dem Bsp1. Und wie man sieht kein gcnew, genau das interessiert mich. Hoffe das war nu verständlich^^.
Edit:
das da gcnew geht weis ich doch, ich will aber eben dahin eine klasse zu schreiben die daten konform eines string aufnimmt, ohne das ich sie vorher initialisieren muss.
-
Ich denke ma das dir da reflection weiterhelfen sollte, sicher bin ich mir aber net...
setzt mal[ComVisible(true)]
vor/über deine Klasse und
[MethodImpl(MethodImplOptions.InternalCall)]
vor/über deinen Constructor, wichtig dabei ist das der Constructor nur ein Parameter haben darf(wenn ich mich net irre) und der eine Parameter ein zeichen-array sein muss (in diesem falls sollte ein char-array das richtige sein)
note:
ComVisible liegt in System.Runtime.InteropServices
MethodImpl liegt in System.Runtime.CompilerServicesedit: ah und ma so btw...
Bsp1:
[GLOBAL]
char *str1;
System::String *str2;[irgendwo im prog lokal]
str1 = "huhu"; // fehler ist ja klar speicher wurde nie reserviert
str2 = "huhu"; // alles in ordnung str2 wird automatisch initialisiertalso mir fallen iwie direkt erstma 4 fehler auf... nur schlimm ist der hier:
str1 = "huhu"; // fehler ist ja klar speicher wurde nie reserviert
les dir plz noma so ein paar grundsachen durch, gerade was speicher reservierung etc betrifft, auch wenn man es in .Net nich mehr so braucht.
-
hmm sieht interessant aus teste das gleich mal danke und was speicherverwaltung angeht brauche ich mir nichts durch zu lesen, habe schlieslich nen eigenen gc geschrieben als ich noch unmanaged geprogt habe, mir ist klar das da ein fehler ist habe ich ja auch dazu geschrieben es dient nur zum vergleich und zur veranschaulichung was ich meine mehr nicht^^. aber das mit internalcall klingt sehr interessant. Danke dir
Edit:
speziell das mit str1 sollte zeigen das da der compiler die definition nicht übernimmt weil er es garnicht übernehmen kann, denn woher soll er sich sicher sein das diese initialisierung auch wirklich statt findet. Im gegensatz dazu System::String da weis es der compiler auch nicht dennoch ist das kein problem also steht da ein prozess wärend der laufzeit dahinter und nicht der compiler. Nur dazu dient Bsp1. (siehe oben wegen aussage das compiler initialisierung übernimmt). Im gegenzug Bsp2, wo der compiler wirklich die initialisierung übernhemen kann weil es fest steht das der wert wirklich zugewiesen wird sobald es zur variable definition kommt.
-
eigenen gc? klingt interessant... öffentlich? link ?
-
nö öhhm wieso auch das ist recht einfach, das sind nur 2 doppelt verkettete listen die über ein interface gefüllt werden sobald ein type initialisiert wird. achja vergessen zu sagen habe es mir da einfach gemacht und von allen standarttypen eigene typen gebaut die sich am interface bedienen also mit den standarttypen von c++ geht mein gc nicht. ist evtl möglich aber echt kein elan das zu schreiben^^. hatte da also meinStrin meinInt mein ....... die erste liste beinhalten pointer auf die variablen (instanzen) die zweite die addressen der instanzen selbst. nun ist damit die erste liste in der lage die aktuellen werte der variablen zu erkennen wärend die 2. liste alle bis dahin aufgetauchten addressen der instanzen/objekte speichert. dann nur noch vergleichen der 1. und 2. liste und addressen die in der 2. liste gefunden werden aber nicht in der ersten werden gelöscht denn diese objekte haben keinen bezug mehr zum programm und liegen einfach nur im speicher ohne das zugriff darauf genommen werden könnte (ausser der 2. liste die ne art history ist der erstellten instanzen). wie gesagt sehr einfach gehalten, aber läuft 1a und ohne leaks. Aber so existiert der gc auch nicht mehr, er iust mittlerweile umgebaut und in ein eigenes datenbanksystem eingebunden. Und an der arbeite ich gerade diese DB hat eine art universaltyp in dem jeder typ (auch in arrayform also array<> und vector<> unterstützung) gespeichert werden kann und auch wieder ausgelesen werden kann von managed sowie unmanaged code. nur ist das doch nen hartes brot. weil arbeite auch an einer funtion die mir jeden datentyp zurück liefert also nicht eine funktion für jeden typ sondern eine für alle und diese soll für managed sowie unmanaged funktionieren. wenn ich damit fertig bin stell ich es gern mal hier rein.
Edit:
auch hier erstelle ich wieder meine eigenen typen die über interfaces an den gc und die db gehen. in dem sinne mache ich es mir wieder einfach. doch das schönste dabei im managed wird fast zu 100% der normale gc umgangen, weil finde den assi nach nem test bei dem ich 1000000 string erstellt habe und wieder gelöscht hatte das prog am ende nen leak von 2,5 MB mein gc dagegen hat nach dem gleichen test nen leak von 0 MB^^
-
aso...
zurück zum thema, da das was ich gepostet habe denk ich mal nicht funktionieren wird, und du dann noma nachfragen wirst, hier schonma die antwortKeywords are predefined reserved identifiers that have special meanings to the compiler. They cannot be used as identifiers in your program unless they include @ as a prefix. For example, @if is a legal identifier but if is not because it is a keyword.
also das gleich was schonma gesagt wurde.... geht net
-
Hallo Oelnsi,
jetzt versuche ich die Runde auch noch etwas durcheinander zubringen.
In erster Line kannst Du den String nicht ohne den Dach (^) in C++/CLI verwenden.Der String^ landet grundsätzlich auf dem verwalteten Heap.
Aus technischer Sicht handelt es sich beim Datentypen String um eine Sonderform eines Arrays, die weitgehend vom Compiler verwaltet wird.
Da das Dach(^) und gc in gcnew für Garbage Collected (Müllhalte) steht.
Das heißt im Einzelnen, dass der GC wird von Zeit zu Zeit ausgelöst.
Zeiger, Pointer, Handels usw. die mit gcnew vereinbart wurden, aber kein zugriff mehr erfolgt, da die Methode schon verlassen wurde, werden aus dem Speicher entfernt.
Dadurch sollen keine "Leichen" mehr im Speicher liegen.
Nun noch weinig zum Thema Destruktoren un Finalisierer.
Dann kommt ein wenig Code…
Die Destruktoren "~Form1()" und Finalisierer "!Form1()" sind das Gegenstück zum Konstruktor.
Sie werden bei der Zerstörung einer Instanz aufgerufen.
Ein Destruktor wird ausgeführt, wenn eine Instanz „per Hand“ zerstört wird, z.B. durch delete.
Der Finalisierer dagegen wird ausgeführt, wenn der Speicher durch die Garbage Collection aufgeräumt wird.
Wobei Speicherlücken entstehen können.Solltest Du zum Beispiel delete vari1; ausführen, wird vari1 freigeben und bei der nächsten Ausführung vom GC gelöscht und somit wieder Speicher freigegeben.
public: String^ vari1; String^ vari2; private: System::Windows::Forms::Button^ button1; public: Form1(void) { InitializeComponent(); // //TODO: Konstruktorcode hier hinzufügen. // vari1 = nullptr; vari2 = nullptr; }
//Button Click... private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { vari1 = "vari1"; vari2 = "vari2"; MessageBox::Show(vari1,vari2); }
Jetzt kommt noch ein ganz fieses Beispiel.
Leg mal eine normale Konsole an, lösch bitte den kompletten Code aus der *.cpp und füge den nachstehenden Code ein und führe das Programm über Strg+F5 aus.// Destrukter und Finalisierer.cpp: Hauptprojektdatei. /*################################################################# Destruktor und Finalisierer ##################################################################*/ #include "stdafx.h" using namespace System; //die Klasse sherry ref class sherry { Int32 alter; Int32 liter; public: //der Konstruktor sherry(Int32, Int32); //der Destruktor ~sherry(); //der Finalisierer !sherry(); void ansehen(); }; //die Methode für den Konstruktor sherry::sherry(Int32 tAlter, Int32 tLiter) { alter = tAlter; liter = tLiter; } //die Methode für den Destruktor sherry::~sherry() { //bitte in einer Zeile eingeben Console::WriteLine("Der Destruktor für den {0} Jahre alten Sherry wurde aufgerufen.",alter); } //die Methode für den Finalisierer sherry::!sherry() { //bitte in einer Zeile eingeben Console::WriteLine("Der Finalisierer für den {0} Jahre alten Sherry wurde aufgerufen.",alter); } void sherry::ansehen() { //bitte jeweils in einer Zeile eingeben Console::WriteLine("Der Sherry ist {0} Jahr(e) alt.",alter); Console::WriteLine("Die Flasche enthält {0} Liter.",liter); } //eine Funktion mit einer lokalen Instanz, die nicht auf dem verwlteten Heap liegt void lokaleInstanz() { sherry flasche4(4,10); } int main(array<System::String ^> ^args) { //Instanzen auf dem verwalteten Heap erzeugen sherry^ flasche1 = gcnew sherry(1,1); sherry^ flasche2 = gcnew sherry(2,1); sherry^ flasche3 = gcnew sherry(3,1); //eine lokale Instanz erzeugen lokaleInstanz(); //Attribute anzeigen flasche3->ansehen(); //Instanz flasche1 per Hand "zerstören" delete flasche1; return 0; }
Hoffe es kommt ein wenig Licht ins Dunkle...
Gruß, Doug_HH
-
verdammt das will ich nicht so hinnehmen, das ist doch mist, naja und wenn ich mit asm alles komplett zerlege ich schaffe das. denn eines ist klar der compiler kann nur vorbereitungen treffen das es dann im prog initiallisert werden kann, aber selber macht er es nicht. Denn es geht ja nicht nur mit const char usw. sondern auch mit variablen wodurch der compiler nichmal wissen kann was für eine länge der string hat sondern erst zur laufzeit feststellbar ist. das heisst wo meine stringvariable steht fügt er was spezielles ein was er bei anderen klassen nicht einfügt, anders geht es ja garnicht. und dort will ich ran, bzw wissen was er da genau einfügt. Trotzdem danke für eure Hilfe
-
das ist zwar schön und nett aber ?? ich meine ich weis wie ich lösche und der gleichen dennoch hat der gc leaks, zudem bestrifft das nichtmal mein problem. Dennoch schönes Bsp. Danke
-
@Doug_HH:
die xte unnötige Hilfe...@oelsni:
solangsam geb ich es auf xD
Wir verstehen schon was du willst.... schon beim 2ten post^^ aber die Antwort ist immer gleich. Der compiler macht das von sich selber aus(jo, asm is ne möglichkeit... aber ob sich DER aufwand sich dafür lohnt?? und irgendwann kommtn update und is wida alles futsch xD)nur noma so btw (brauchst auf diesen abschnitt nix zu posten^^, schreibe es ma kurz in C#):
string foo = "bar";
ist equivalent zu
char[] chars = new char[]{'b','a','r'}; String foo = new String(chars);
thema für mich closed //evtl noch offtopic
-
nee ist auch alles geklärt kann mir vorstellen was der compiler da in etwa macht. und mir egal ich will den LUXUS^^
ich meine es geht ja auch so aber bin halt nen druff mehr gibt es da nicht zu sagen *g Ich drück die scheise mit asm durch ist zwar eine sehr unschöne methode aber am ende sieht es so aus wie bei System::string freu mich schon auf die arbeit juhuu:p
P.S.: wenn ich eine edle methode finde das zu realisieren stell ich dir hier rein damit euch die kinnlade einschläft
bis dahin nix mehr hier schrieben ausser ihr habt bock drauf für mich ist die sache geklärt.