gelöst (Cpp) Verständnisproblem: Nutzen des new-operators? (mit Beispiel)

Mitglied: SinixND

SinixND (Level 1) - Jetzt verbinden

26.10.2020, aktualisiert 01:47 Uhr, 631 Aufrufe, 20 Kommentare

Hallo liebe community!

INTRO:
Zunächsteinmal: Trotz mehrerer Stunden Recherche habe ich für meine Frage leider noch keine Antwort gefunden und wende mich daher vertrauensvoll an dieses Forum. Ich war früher schon mal einige Zeit hier unterwegs, habe mich aber damals mit Batch beschäftigt =) Das Forum blieb mir immer in seeehr guter Erinnerung.

Aufgrund meiner in absehbarer Zeit anstehenden Bachelorarbeit im Maschinenbau-Studium, bei der ich ein Programm in C++ schreiben kann/muss/darf/soll (=D), beschäftige ich mich nun seit einigen Tagen relativ intensiv mit C++, mit welcher ich vorher noch nie Kontakt hatte.

Mittlerweile bin ich bei "Dynamischen Strukturen - Anlegen und Freigeben von Speicher" angekommen (aus der von meinem Prof. vorgeschlagenen online-version des Buches "Einstieg in C++" von Willemer ; ich nutze auch andere Quellen wie youtube, google und die cpp-Einführung auf highscore.de, die aber keinen http-link hat, daher möchte ich sie nicht verlinken)

FRAGE:
Mir erschließt sich die Nutzung des new-operators nicht. Warum nutzt man ihn? Welche Vor- oder Nachteile hat er im Vergleich zu anderen Möglichkeiten? Ich komm nicht drauf.

BEISPIEL:
in einem youtube-guide (link) fand ich ein schönes Beispiel, bei dem mein "Problem" hoffentlich klar wird. Das Programm erzeugt eine Matrix (als Vergleich wurde ein Bild genannt), welche dann mit 0-ern gefüllt wird. Als Anzahl für Zeilen (r) und Spalten (c) übernahm ich r=800 und c=600 aus dem video. Beide Varianten funktionieren meines Erachtens einwandfrei. Daher ist mir der Vorteil der ersten nicht ersichtlich.

Beide codes (der auskommentierte original-code sowie mein eigener Versuch) Haben das gleiche Ergebnis.
Daher stellt sich mir die Frage, wozu man den new-operator braucht. Offensichtlich (für mich) kann man auch ohne new-operator während des laufenden Programms Variablen/Matrizen und so deklarieren, die dann auf Nutzereingaben (oder vermutlich auch anderen Input) reagieren und sich so dem Bedarf anpassen.

SCHLUSS
Ich hoffe, dass mein Problem ersichtlich wurde und mir jemand helfen kann =)

Sollte ich irgendetwas vergessen haben, möchte ich mich im Voraus dafür entschuldigen und werde es natürlich baldmöglichst korrigieren. Verzeigt bitte auch, sollte ich manche Begriffe falsch benutzt haben, auf die paar Tage kenne ich natürlich vieles noch nicht und bin mit der Verwendung der Fachbegriffe uU. noch nicht ganz vertraut ;) Sollten mehr Kommentare im Code erwünscht sein, ergänze ich sie gerne.

Vielen Dank schon mal an alle Kommentatoren

SinixND
Mitglied: mayho33
26.10.2020 um 02:05 Uhr
Hi,

Wenn du vor dem Bachelor stehst, solltest du ja schon einige Berührungspunkte haben mit C++. Vorausgesetzt du hast da nicht gefehlt

Der New() -Operator erzeugt in fast allen Programmiersprachen eine neu Instanz des angegebenen Objekts

Powershell:
$a = New-Object ...

C#:
Object x = New Directoryinfo()....

Dito in cpp usw.

Hier die Referenz zu den Keywords:

https://en.cppreference.com/w/cpp/keyword

Grüße!
Bitte warten ..
Mitglied: SinixND
26.10.2020, aktualisiert um 02:14 Uhr
naja, es ist ein Maschinenbau-Bachelor, wir hatten 1 Semester visual basic, das wars ;)

back to topic:
auch eine Variablen-deklaration erzeugt doch eine neue Instanz, oder? wo ist also der mehrwert ggü. der (viel kürzeren) Variante?

den Link schau ich mir mal an ;)
Bitte warten ..
Mitglied: KLinnebank
26.10.2020 um 08:48 Uhr
Moin zusammen,

kurz und simpel ausgedrückt:

Das erste Beispiel erzeugt und verwendet ein Objekt (naja, eigentlich eine Liste von Objekten)
im dynamisch "allgemeinen Speicher". Der Operateor delete gibt diesen Speicher wieder frei.
Das Objekt kann duch Dein Programm und seine Funktionen durchgereicht werden und darf nur von
Deinem Programm zerstört werden zu einem Zeitpunkt, den Du kontrollierenkannst.

Dein Beispiel erzeugt ein lokales Speicherobjekt, das nur Gültigkeit besitzt
innerhal Deiner lokalen Funktion, es wird automatisch beim Verlassen der Funktion zerstört
und kann nicht (zumindest nicht "nach oben" zurück) weitergegeben werden.

ICh hoffe, ich konnte rüberbringen, was ich meine....

Mfg

KLinnebank
Bitte warten ..
Mitglied: rubberman
26.10.2020 um 08:52 Uhr
Wenn du new in C++ nutzt, hast du im Zweifelsfall einen Designfehler in deinem Programm. Wenn du new ohne Verwendung eines Smartpointers verwendest, hast du definitiv etwas falsch gemacht. Die Gefahr eine Speicherverletzung zu verursachen ist zu groß, darum baut C++ auf das RAII Prinzip. In deinem Fall würde man eine der STL Containerklassen nutzen. Youtube ist in aller Regel kein guter Anlaufpunkt um Programmieren zu lernen...

Steffen
Bitte warten ..
Mitglied: SinixND
26.10.2020 um 09:17 Uhr
von dem Vorteil von Smartpointern hab ich schon gehört.
Vorrangig geht es mir ums Verständnis des neu-operators. Schadet bestimmt auch für die Verwendung von Smartpointern nicht.
Youtube kam erst bei der Suche nach einem Eklärungsversuch ;)

Danke trotzdem
Bitte warten ..
Mitglied: rubberman
26.10.2020, aktualisiert um 10:07 Uhr
Gut, was new macht ist glaube ich hinreichend erklärt. Es stellt dir Speicher vom Stack zur Verfügung, der dann durch delete wieder freigegeben muss. Bei Smartpointern erledigt letzteres der Destruktor.

Anmerkung noch zu deinem eigenen Code - du erzeugst ein sogenanntes Variable Length Array (VLA). Das wird auf dem Heap allokiert. Geht ganz schnell ohne jede Vorwarnung in die Hose wenn du zu viele Elemente allokieren musst und solltest du unter allen Umständen vermeiden!

Steffen
Bitte warten ..
Mitglied: SinixND
26.10.2020, aktualisiert um 10:18 Uhr
Das heißt sozusagen:
Im Gegensatz zu
kann auf
überall im Programm (also auch außerhalb der entsprechenden Klammer) zugegriffen werden...
Bitte warten ..
Mitglied: rubberman
26.10.2020 um 10:59 Uhr
Speicher wird für deinen Prozess allokiert. Der ist also grundsätzlich global gültig. Variablen, die den Speicher ggf. referenzieren, haben aber nur Gültigkeit für das Scope in dem sie deklariert wurden. Da liegt der Unterschied.

Steffen
Bitte warten ..
Mitglied: SinixND
26.10.2020, aktualisiert um 12:00 Uhr
ah, das war in etwa dass, was ich gesucht hab
wenn ich mein wissen jetzt mal zusammenfasse:

- new ist "persistent" bis "delete", die variable gilt also auch außerhalb (über/unter?) der klammer(scope)
- new weist der erstellten variable/array auch gleich einen Zeiger zu, was sonst in zwei schritten gemacht werden müsste
- new erlaubt (noch nicht im skript definierte) variablen in arrays (entspricht definition zu laufzeit?). dies geht bei einer "normalen" array-deklaration nicht (entspricht definition zu kompilier-zeit?)

bin mir nur bei allen Punkten nich sicher, ob das stimmt…
Bitte warten ..
Mitglied: rubberman
LÖSUNG 26.10.2020 um 12:02 Uhr
- new ist "persistent" bis "delete", die variable gilt also auch außerhalb (über/unter?) der klammer
Hmpf. Der Pointer (die Adresse des allokierten Speichers) bleibt gültig. Variablen selber haben aber immer eine definierte Sichtbarkeit (Scope). Du kannst also nicht einfach eine Variable foo in der main deklarieren und ihr einen allokierten Pointer zuweisen, und anschließend davon ausgehen dass du die Variable foo in einer anderen Funktion verwenden kannst. Du kannst einen allokierten Pointer aber aus einer Funktion zurückgeben, ohne Gefahr zu laufen dass er ungültig wird.

- new weist der erstellten variable/array auch gleich einen Zeiger zu, was sonst in zwei schritten gemacht werden müsste
Was meinst du mit "sonst"? Du allokierst so etwas wie ein zweidimensionales Array. Dazu wird ein Array von Pointers auf int allokiert, der die "Zeilen" als Elemente beinhalten. Für jede Zeile muss aber noch mal ein Array von int allokiert werden für die Einzelwerte einer Zeile. Jeder dieser Pointerwerte muss mit delete wieder freigegeben werden. Da reden wir also von wesentlich mehr als nur zwei Schritten.

- new erlaubt (noch nicht im skript definierte) variablen in arrays (entspricht definition zu laufzeit?). dies geht bei einer "normalen" array-deklaration nicht (entspricht definition zu kompilier-zeit?)
Richtig. Wenn die Größe erst zur Laufzeit festgelegt wird, baust du ansonsten ein VLA.

Aber ich muss noch mal klar darauf hinweisen, dass das kein gutes C++ wird. Die STL bietet dir hier std::array oder std::vector für solche Zwecke …

Steffen
Bitte warten ..
Mitglied: SinixND
26.10.2020 um 13:03 Uhr
vielen Dank für die ausführliche Antwort
sie hat auf jeden Fall viel geholfen

zu 1) dh, obwohl die Variable außerhalb des scopes nicht mehr ansprechbar ist, bleibt der zugewiesene pointer ansprechbar?

2) mit "sonst" meinte ich, dass man sonst (1.) bspw. ein array deklarieren muss, auf welches man dann (2.) einen pointer referenziert.
ich wüsste beispielsweise gar nicht, wie ich "nachträglich" pointer auf die elemente eines "int array[5][5]" referenzieren könnte. falls das mit for-schleifen klappt, ist in der hinsicht der new-operator "nur" kürzer zu schreiben.

3) sehr gut
Bitte warten ..
Mitglied: rubberman
LÖSUNG 26.10.2020, aktualisiert um 13:37 Uhr
zu 1) dh, obwohl die Variable außerhalb des scopes nicht mehr ansprechbar ist, bleibt der zugewiesene pointer ansprechbar?
Er bleibt gültig. Aber ohne Variable (die nichts anderes tut als den Pointer/die Adresse zu speichern) hast du keinen Zugriff. Und genau da liegt die Gefahr. Verlierst du die Adresse (indem eine Variable überschrieben oder ungültig wird, oder indem der ursprüngliche Pointerwert durch Pointerarithmetik verändert wurde), dann kann er nicht mehr freigegeben werden und du erzeugst ein Speicherleck.

2) mit "sonst" meinte ich, dass man sonst (1.) bspw. ein array deklarieren muss, auf welches man dann (2.) einen pointer referenziert.
ich wüsste beispielsweise gar nicht, wie ich "nachträglich" pointer auf die elemente eines "int array[5][5]" referenzieren > könnte. falls das mit for-schleifen klappt, ist in der hinsicht der new-operator "nur" kürzer zu schreiben.
Ein Array ist immer gleichzeitig ein Pointer. Im Gegensatz zu einer Arrayvariablen enthält aber eine Pointervariable keinen Hinweis mehr, auf wie viele Elemente verwiesen wir. Man spricht von Array-To-Pointer-Decay.

Ich hatte da vor einiger Zeit mal was dazu runtergeschrieben …
https://dev-community.de/resources/c-pointer.6/

Steffen
Bitte warten ..
Mitglied: SinixND
26.10.2020, aktualisiert um 19:01 Uhr
[OT]

dein link ist sehr interessant. Wenn ich mir (bin jetzt zur hälfte durch) einen Kommentar/Frage/Verbesserungsvorschlag erlauben darf:

mir wurden Pointer in dem oben erwähnten Buch mit folgendem Beispiel zum ersten Mal gezeigt:
Ich als Newbie hab das so gelesen:
char - das ist der pointertyp
*charZeiger - das ist der pointername

und hab daraus gefolgert, dass ein pointer über das " * " am Namensanfang identifiziert und von normalen Variablen unterschieden wird.
Diese Schreibweise habe ich auch in deinem Guide gefunden.

Inzwischen weiß ich aber, dass der Inhalt eines int-Pointers ein anderer ist als der einer int-Variable.

Daher hat der Pointer genaugenommen einen anderen Typ, nämlich int* (wodurch das Programm ganz klar weiß: Jetzt lege ich einen Pointer für eine int-Variable an, und keine int-Variable).
Ich denke deshalb, dass
die verständlichere, intuitivere Schreibweise ist =)

Oder gibt es einen bestimmten Grund, lieber "int *p" anstatt "int* p" zu schreiben?
Bitte warten ..
Mitglied: rubberman
26.10.2020 um 19:15 Uhr
Darüber scheiden sich die Geister. Erstmal
int *p;
ist dasselbe wie
int * p;
ist dasselbe wie
int* p;

In Punkto intuitiv kannst du auf die Nase fallen. Beispiel:
int* p, x;
Wenn du jetzt denkst, dass x auch ein Pointer ist, liegst du verkehrt, denn x ist ein int. Darum ziehe ich das Asterisk vor den Variablenname:
int *p, *x;
Nun ist klar, auch x ist ein Pointer Aber wie gesagt, das ist lediglich eine Frage des Stils, den du für dich selbst finden musst, dann aber möglichst konsistent verwenden solltest um den Leser des Codes nicht zu verwirren.

Steffen
Bitte warten ..
Mitglied: SinixND
26.10.2020 um 19:26 Uhr
ah ich verstehe, das macht dann natürlich Sinn (und ist gleichzeitig etwas doof.. xD)
Bitte warten ..
Mitglied: mayho33
27.10.2020 um 10:08 Uhr
Zitat von SinixND:
auch eine Variablen-deklaration erzeugt doch eine neue Instanz, oder? wo ist also der mehrwert ggü. der (viel kürzeren) Variante?

Wenn du eine Variable deklarierst, dann erstellst du ein neues Object der BASE (z.B. String), das stimmt. der New-Operator erstellt aber eine neue Instalnz des Objects das du schon erstellt hast.

bsp:
Grüße!
Bitte warten ..
Mitglied: SinixND
27.10.2020, aktualisiert 28.10.2020
soweit ich das jetzt verstanden hab erstellt new schon auch neue Variablen, aber der speicher wird nicht automatisch wieder freigegeben, sobald die klammer der erstellten variable verlassen wird. außerdem gibt new die adresse zurück, nicht den Wert.

funktioniert einwandfrei. Die Variable hat zwar keinen Namen, aber p zeigt auf die Variable ohne Namen. Allerdings kann man mit der auskommentierten Zeile *p nicht mehr ausgeben, also die erstellte Variable und der Zeiger sind nicht mehr aufrufbar, sobald das scope verlassen wurde. Deshalb verstehe ich die Existenz des new befehls nicht (abgesehen davon, dass man sich die Benennung der Variable spart xD).

Ich weiß inzwischen, dass der new-Befehl sehr unbeliebt ist, weil man viele Fehler machen kann und es wohl sowohl dafür als auch für Pointer bessere Lösungen gibt. Ich Frage nur um des Wissens willen =)
Bitte warten ..
Mitglied: mayho33
29.10.2020 um 10:03 Uhr
Zitat von SinixND:

Ich weiß inzwischen, dass der new-Befehl sehr unbeliebt ist, weil man viele Fehler machen kann und es wohl sowohl dafür als auch für Pointer bessere Lösungen gibt. Ich Frage nur um des Wissens willen =)


Ist schon einige Zeit her, da ich mich mit cpp gespielt habe, aber wenn sich nichts geändert hat dann ist das Problem immer noch der Carbagecollector. Der Destruktor der BASE wird nicht automatisch aufgerufen und dein Objekt existiert bis zum Nimmerleinstag. Ergo: irgendwann gibts einen Stackoverflow.

In C# passiert das automatisch. Und da ist der New-Operator bei einigen Dingen ein muss weil Instanzen nur so vererbt werden können. Da gibts allerdings auch keine Pointer, alloc usw. Alles automatisiert.

Grüße!
Bitte warten ..
Mitglied: rubberman
29.10.2020 um 18:26 Uhr
Carbagecollector
In C++? Nee, da gibt's so etwas nicht. C# unterscheidet sich da grundlegend. Auch hinsichtlich new, das man in C++ nur in Ausnahmefällen verwendet und, wie schon geschrieben, ohne Smart Pointer Klasse baut man mit new gleich mal grundsätzlich einen Designfehler in den Code.

Steffen
Bitte warten ..
Mitglied: mayho33
30.10.2020 um 00:49 Uhr
Zitat von rubberman:

Carbagecollector
In C++? Nee, da gibt's so etwas nicht. C# unterscheidet sich da grundlegend. Auch hinsichtlich new, das man in C++ nur in Ausnahmefällen verwendet und, wie schon geschrieben, ohne Smart Pointer Klasse baut man mit new gleich mal grundsätzlich einen Designfehler in den Code.

Steffen

Wusste ich doch dass es einen Grund hatte warum ich mit cpp aufgehört habe
Bitte warten ..
Heiß diskutierte Inhalte
Off Topic
Wie geht ihr mit grantigen "Kunden" um?
AbstrackterSystemimperatorErfahrungsberichtOff Topic24 Kommentare

Moin Kollegen, mal eine Offtopic Frage in die Runde gestellt. Wie geht ihr mit grantigen "Kunden" (interne IT) / ...

Windows Server
Druckserver Domäne GPO
arik12FrageWindows Server22 Kommentare

Hallo zusammen, Ich möchte einen Druckserver einrichten und Drucker auf dem Druckserver installieren. Die Drucker sollen dann per GPO ...

Netzwerke
Sicherheitsbetrachtung virtualisierte Umgebung
gelöst Philipp711FrageNetzwerke22 Kommentare

Hallo liebe Community, ich habe eine kleine Frage bzgl. der Netzwerksicherheit in virtualisierten Umgebungen. Beispiel: Ich habe einen Hypervisor ...

Exchange Server
Exchg2016: ECP-Anzeigefehler oder echtes Problem?
winackerFrageExchange Server13 Kommentare

Hallo, mein Exchg16 (auf SRV16) hat ein Phäomen was bislang keiner aufklären kann - und ich weiß nicht ob ...

Off Topic
Adventskalender 2020
LochkartenstanzerInformationOff Topic12 Kommentare

Was haltet ihr von einer Sammlung von Adventskalendern? (Hier im Thread z.B.) Ich fang mal mit dem Heise-Kalender an: ...

Server-Hardware
Hp Proliant ml350 g5 kommt nicht zum POST
jetstream3000FrageServer-Hardware12 Kommentare

Hallo Forum So hab mir einen Hp Server zum herumprobieren gekauft hat auch alles funktioniert hat zwei Intel Xeon ...

Ähnliche Inhalte
Exchange Server
New-PublicFolderMoveRequest
gelöst IxxZettFrageExchange Server2 Kommentare

Hallo zusammen, derzeit habe ich unseren Exchange noch auf dem DC (Exch2016 auf WS2012R2) das war noch nie gut ...

Webbrowser

Firefox 68.0.2 nutz Windows-Zertifikatsspeicher nichtmehr

PN-SchrauberFrageWebbrowser5 Kommentare

Hallo Gemeinde, ich habe mal wieder ein Problem, und zwar nutzen wir für unser Intranet Zertifikate unserer eigenen CA. ...

Batch & Shell

New-PSDrive im Skript

gelöst erikroFrageBatch & Shell2 Kommentare

Moin, gleich vorweg: Es ist keine Domain vorhanden. Gruppenrichtlinien fallen also weg. Bisher wird den Usern eine Freigabe per ...

Exchange Server

Problem mit New-PublicFolderMoveRequest

IxxZettFrageExchange Server1 Kommentar

Hallo, ich habe testweise in einen zweiten Exchange 2016 in einer Domäne installiert (Ws2012R2) und testweise ein Userpostfach über ...

Windows Server

SCCM Powershell New-CMDetectionClauseRegistryKeyValue

gelöst mayho33FrageWindows Server1 Kommentar

Hallo @ All Ich hänge wieder mal bei einem der (Sarkasmus) bestens dokumentierten SCCM-CmdLets und MS schweigt sich aus ...

Windows 10

Windows 10 Apps (als Beispiel Skype)

SonnyHHFrageWindows 103 Kommentare

Hallo all Ich bin kein Experte in Sachen GPO. Ich habe folgendes Problem. Melde ich mich an einem Rechner ...

Neue Fragen
Administrator Magazin
11 | 2020 Virtualisierung ist aus der IT nicht mehr wegzudenken. In der November-Ausgabe des IT-Administrator Magazins dreht sich der Schwerpunkt um das Thema "Server- und Storage-Virtualisierung". Darin erfahren Sie, wie sich die Virtualisierungstechnologie entwickelt hat, welche Varianten es im Bereich Server und Speicher gibt und wie ...
Neue Beiträge
Neue Jobangebote
Server- und Storage-VirtualisierungServer- und Storage-VirtualisierungBerechtigungs- und IdentitätsmanagementBerechtigungs- und IdentitätsmanagementWebdienste und -serverWebdienste und -serverDatenbankenDatenbankenMonitoring & SupportMonitoring & SupportHybrid CloudHybrid Cloud