Hab ich hier eventuell etwas nicht berücksichtigt?
-
Ynnus schrieb:
Pseudocode: (syntaktisch falsch) // schon mal ganz schlecht char* Funktion() { char* buffer = new char* [20] // das verwirrt nur, deshalb immer richtig schreiben buffer = "Bla bla bla" // std::strncpy nehmen return buffer }Mir ist dabei klar, dass der Speicher nicht freigegeben wird und somit verfault. Das soll nicht sein, daher habe ich mir eine Methode überlegt, mit der ich der Funktion ein Objekt übergebe welches einen pointer enthält. Dann kann die Funktion den Pointer manipulieren wie sie will und Dinge hinein schreiben. Wenn das Objekt dann aus dem Scope fällt und der destruktor aufgerufen wird, wird der allokierte Speicher freigegeben.
Richtig. Gute Idee.
Das Objekt soll aber nicht innerhalb der Funktion erzeugt werden da der Speicher dann bei dem Rückgabewert der Funktion schon freigegeben werden würde. Das Objekt mit dem Pointer wird also im Hauptcode erstellt, von dem aus dann die Funktion aufgerufen wird.
Du musst einen Copyconstructor und einen operator= definieren.
#include <iostream> using namespace std; class pointer_class // Klassennamen werden meist groß geschrieben { private: int size; // sollte size_t sein, weil z.b. strlen auch mit size_t arbeiten char* pointer; // siehe data() public: const char* getData() const { return pointer; } // edit: es sollte getData und nicht nur "data" heißen bool change_size(int new_size, bool flag = false); // die funktionen von variablen sollten durch den namen erkennbar sein // vielleicht solltest du dich entscheiden, ob du minimale prototypen schreibst, oder immer gleich die namen mit angibst bool write( char*, int = -1); pointer_class( int ); ~pointer_class( void ); // void muss nur in c da stehen }; bool pointer_class::write( char* new_content, int length) { if (length == -1) { length = strlen( new_content ); } if (length <= size) //only if pointer is holding enough memory { std::strcpy(pointer, new_content); // strcpy, weil das ziel groß genug ist return true; } return false; } bool pointer_class::change_size(int new_size, bool flag) { //flag true = keep content //flag false = clear content if (flag) { if (size > 0) { /* char* old_content = new char [size]; //allocate memory for old content to keep it memcpy(old_content, pointer, size); // hier wieder dasselbe mit std::strcpy delete [] pointer; //delete pointer for reallocating soon with new size pointer = new char [new_size]; //allocate new memory memset(pointer, 0, new_size); //unnötig, wird sowieso gleich überschrieben memcpy(pointer, old_content, new_size); //fill in old memory till end of new buffer or till everything is in delete [] old_content; //delete temporary buffer for old content; size = new_size; //set new size return true; */ char* content = new char[new_size]; std::strncpy(content, pointer, new_size); delete [] pointer; pointer = content; } else { pointer = new char [new_size]; memset(pointer, 0, new_size); } size = new_size; return true; } else //clear content { if (size > 0) delete [] pointer; pointer = new char [new_size]; memset(pointer, 0, new_size); size = new_size; return true; } return false; } // lieber zwei Konstruktoren nehmen, einer mit size_t und einer ohne argumente pointer_class::pointer_class( int p_size) : size(p_size) // ist in mehr als 50% der fälle richtig { if (p_size > -1) // wir wollen schließlich keine ungültigen argumente für new { pointer = new char [size]; memset(pointer, 0, size); } else { pointer = 0; // NULL ist deprecated (oder so) size = 0; } } pointer_class::~pointer_class( void ) { if (size) delete [] pointer; }Mir ist bewusst, ich begehe da schwere OOP-Fehler da der Pointer im Public bereich ist und somit frei manipuliert werden kann. Doch anders lässt es sich manchmal nicht machen (da manche WinAPI-Funktionen den reichen Pointer als Parameter benötigen und wenn der geschützt ist die Funktion einen Zugriffsfehler rausgibt). Daher brauche ich manchmal den ungeschützten reinen pointer aus dem Objekt welcher deshalb public ist.
Schau dir mal std::string::data() und std::string::c_str() an.
Ansonsten ist grundsätzlich von ungeschütztem Datenverkehr abzuraten.
Das sah eigentlich alles richtig aus, habe es aber nicht compiliert.
Sieh das aber nur als Übung an und benutze ansonsten immer std::string.mfg
-
Wenn du weiter so programmierst wird dein Programm aber nicht gut!
-
ness schrieb:
Btw: Das nennst sich smart pointer, kannst ja mal danach googlen.
Da wird zwar auch Speicher freigegeben, aber das hier ist immer noch ein Container und ein std::string/vector<char> Ersatz.
mfg
-
terraner schrieb:
Du musst einen Copyconstructor und einen operator= definieren.
oder deine Klasse von boost::noncopyable erben lassen
-
@Ynnus
ich würde dir auch raten, dich mit den stl-klassen vector und string zu befassen. das ist zwar erst mal ein gewisser lernaufwand, der zahlt sich aber in jedem fall aus!
-
Wenn du weiter so programmierst wird dein Programm aber nicht gut!
Ok, ich hab ja schon verstanden, dass ich das nur unnötig kompliziert mache und besser auf vorhandene C++ Klassen zurückgreifen. Aber mal ganz unabhängig vom Gefallen am Programmierstil, solange keine Fehler drinne sind, hat es doch keine Auswirkungen darauf, wie gut das Programm wird.
Vielleicht darauf, dass es ein bisschen mehr Rechenleistung benötigt oder weniger Schleifendurchläufe pro Sekunde hinlegt. Aber sonst hat doch der Stil des Programmes wenig Auswirkungen auf das Resultat.
Wo genau ist denn der Knackpunkt (außer, dass ich C unc C++ mische) der das Programm so schlecht macht? Irgendwelche groben Verstöße beim Speichermanagement? Und das Variablen mal public sind lässt sich manchmal leider (scheinbar?) nicht umgehen. Beispiel: Die WinAPI benötigt des öffteren einen Speicherbereich um dort Werte hinein zu schreiben. Wenn ich nun den Pointer im Private Bereich des Objekts habe, wie kann ich den dann übergeben? Dann wird mir das Programm wohl mit einem Schreibsfehler abschmieren weil jemand in den Private-Bereich eines Objekts schreiben wollte. Oder gibt es da mir unbekannte Möglichkeiten, doch in die Private Variablen zu schreiben von Außerhalb? Ist ja auch nicht Sinn von OOP, daher hab ich die Variable gleich public gesetzt.
-
was spricht gegen eine get-memberfunktion?
-
public var schrieb:
was spricht gegen eine get-memberfunktion?
Ist der Private-Breich eines Objekts nicht in so fern geschützt, dass man Veränderungen NUR innerhalb der Klasse und deren Methoden vornehmen kann? Selbst wenn ich dann den Pointer per return zurückgebe und an die WinAPI-Funktion übergebe, sobald die Funktion den Inhalt ändern will, stürzt das Programm ab. Oder liege ich da falsch?
-
Liegst falsch!
-
Ich bin ja froh, dass einige hier so humorvoll sind. Hast du keinen Nick oder wie?
Ich hab's jetzt umgestellt, der Pointer ist nun private und wird per get_pointer() zurückgegeben. Ich hatte wohl damals was unglücklich falsch gemacht wodurch ich nun irrtümlich dachte, der Speicherbereich sei besonders geschützt, sodass man da eben nur durch klasseneigene Methoden reinschreiben kann. Damals gabs eben, wie gesagt, einen Speicherfehler, damit hatte sich das dann für mich erledigt.
Aber ich habs jetzt umgeändert.
-
Würde nicht auto_ptr aus der STL (memory) das selbe machen?
-
gurru schrieb:
Würde nicht auto_ptr aus der STL (memory) das selbe machen?
hier is es etwas doof, da der pointer keinen op[] hat.(Ansonsten is es natürlich ok, wenn man mit dem vergleicht, was der threadstarter benutzt
)
-
otze schrieb:
gurru schrieb:
Würde nicht auto_ptr aus der STL (memory) das selbe machen?
hier is es etwas doof, da der pointer keinen op[] hat.(Ansonsten is es natürlich ok, wenn man mit dem vergleicht, was der threadstarter benutzt
)Es wäre aber einfacher, die Klasse dann von auto_ptr abzuleiten, und dann darin den Operator[] zu definieren.
-
otze schrieb:
Ansonsten is es natürlich ok, wenn man mit dem vergleicht, was der threadstarter benutzt


das ist noch doofer, hier std::auto_ptr zu benutzen, als was threadstarter vorgeschlagt hat
Werf mal enen Blick in std::auto_ptr::~auto_ptr. Da findest zu sowas:~auto_ptr() { delete _M_ptr; }
Das nennt sich Undefined behaviour, da hier operator delete [] benutzt werden muss. Also bitte boost::scoped_array anstatt std::auto_ptr benutzen!!!
-
gurru schrieb:
Es wäre aber einfacher, die Klasse dann von auto_ptr abzuleiten, und dann darin den Operator[] zu definieren.

-
Es wäre aber einfacher, die Klasse dann von auto_ptr abzuleiten, und dann darin den Operator[] zu definieren.
Ja ne is klar...
-
ssm schrieb:
das ist noch doofer, hier std::auto_ptr zu benutzen, als was threadstarter vorgeschlagt hat

Werf mal enen Blick in std::auto_ptr::~auto_ptr. Da findest zu sowas:~auto_ptr() { delete _M_ptr; }OK, das hab ich übersehen. (Also vergessen)