Skip to content

Commit 7b260e5

Browse files
authored
homework: finalize B07 (#379)
1 parent 24964bc commit 7b260e5

File tree

1 file changed

+51
-56
lines changed

1 file changed

+51
-56
lines changed

homework/sheet07.md

Lines changed: 51 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,11 @@ points: 10 Punkte
55
title: "Blatt 07: C++"
66
---
77

8-
::: center
9-
**Wir arbeiten gerade an dieser Seite ...**
10-
:::
11-
12-
<!--
138
# Zusammenfassung
149

1510
Ziel dieses Aufgabenblattes ist die praktische Anwendung Ihrer C++-Kenntnisse,
1611
insbesondere werden Sie Pointer, Referenzen und Klassen anwenden und vertiefen. Als
17-
Anwendungsbeispiel werden Sie bestimmte in der C++-Welt wohlbekannte Smartpointer
12+
Anwendungsbeispiel werden Sie bestimmte in der C++-Welt wohlbekannte Smart-Pointer
1813
modellieren sowie einen einfachen Ringpuffer programmieren. Sie lernen mit dem
1914
*Reference Counting* nebenbei eine verbreitete Technik der *Garbage Collection*
2015
kennen.
@@ -131,23 +126,23 @@ ist. Ein Aspekt dabei ist, dass man häufig die Freigabe der Objekte vergisst od
131126
dass die Programmpfade so unübersichtlich sind, dass man nicht genau weiss, ob und
132127
wann man Objekte freigeben soll (denken Sie an Exceptions).
133128

134-
## Smartpointer als Lösung
129+
## Smart-Pointer als Lösung
135130

136131
Während man in Sprachen wie Java die Speicherverwaltung komplett dem Compiler
137132
überlässt oder wie in Rust mit strikten Ownership-Modellen arbeitet, hat man in C++
138133
die sogenannten
139-
[Smartpointer](https://en.cppreference.com/book/intro/smart_pointers) erdacht. Diese
140-
ersetzen den direkten Umgang mit den einfachen Pointern (auch als *raw pointer*
141-
bezeichnet) und lösen das Problem der Freigabe der verwalteten Ressourcen.[^2] Es
142-
gibt verschiedene Modelle, insbesondere gibt es die Variante *unique pointer*, bei
143-
der immer nur genau ein Smartpointer gleichzeitig eine bestimmte Ressource besitzen
144-
darf, und die *shared pointer*, bei der mehrere Smartpointer gleichzeitig die selbe
145-
Ressource verwalten können. Sobald die Lebensdauer des *unique pointer* oder des
146-
letzten *shared pointer* endet, wird die verwaltete Ressource automatisch vom
147-
Smartpointer freigegeben.
134+
[Smart-Pointer](https://en.cppreference.com/book/intro/smart_pointers) erdacht.
135+
Diese ersetzen den direkten Umgang mit den einfachen Pointern (auch als *raw
136+
pointer* bezeichnet) und lösen das Problem der Freigabe der verwalteten
137+
Ressourcen.[^2] Es gibt verschiedene Modelle, insbesondere gibt es die Variante
138+
*unique pointer*, bei der immer nur genau ein Smart-Pointer gleichzeitig eine
139+
bestimmte Ressource besitzen darf, und die *shared pointer*, bei der mehrere
140+
Smart-Pointer gleichzeitig die selbe Ressource verwalten können. Sobald die
141+
Lebensdauer des *unique pointer* oder des letzten *shared pointer* endet, wird die
142+
verwaltete Ressource automatisch vom Smart-Pointer freigegeben.
148143

149144
Das folgende Beispiel arbeitet mit einer selbst implementierten Variante der *shared
150-
pointers*. Dabei ist die Klasse `SmartToken` ein Smartpointer für Objekte vom Typ
145+
pointers*. Dabei ist die Klasse `SmartToken` ein Smart-Pointer für Objekte vom Typ
151146
`Token`:
152147

153148
``` cpp
@@ -174,63 +169,64 @@ void fluppie() {
174169
```
175170

176171
Im Beispiel wird mit `new Token("wuppie", 1, 4)` ein neues Token-Objekt auf dem Heap
177-
angelegt. Der Smartpointer `wuppie` übernimmt die Ressource im Konstruktor und
172+
angelegt. Der Smart-Pointer `wuppie` übernimmt die Ressource im Konstruktor und
178173
verwaltet den Pointer. Wichtig ist zu beobachten: Das Token wird auf dem Heap
179-
angelegt, während der Smartpointer `wuppie` eine normale lokale ("automatische")
174+
angelegt, während der Smart-Pointer `wuppie` eine normale lokale ("automatische")
180175
Variable ist und auf dem Stack liegt.
181176

182-
In der Kontrollstruktur werden weitere Smartpointer angelegt. Die ersten beiden
177+
In der Kontrollstruktur werden weitere Smart-Pointer angelegt. Die ersten beiden
183178
(`fluppie`, `fluppie2`) teilen sich die Ressource (den Pointer auf das Token) mit
184-
`wuppie`. Es wird kein neues Token angelegt oder kopiert. Der dritte Smartpointer
179+
`wuppie`. Es wird kein neues Token angelegt oder kopiert. Der dritte Smart-Pointer
185180
`foo` verwaltet ein weiteres Token.
186181

187182
Mit der Kontrollstruktur endet auch die Lebensdauer der lokalen Variablen `fluppie`,
188183
`fluppie2` und `foo`, sie werden automatisch vom Stack entfernt. Da `foo` der letzte
189-
Smartpointer ist, der das Token "foo" verwaltet, wird hier die Ressource
190-
freigegeben. Bei `fluppie` und `fluppie2` werden nur die Smartpointer auf dem Stack
184+
Smart-Pointer ist, der das Token "foo" verwaltet, wird hier die Ressource
185+
freigegeben. Bei `fluppie` und `fluppie2` werden nur die Smart-Pointer auf dem Stack
191186
entfernt, die verwaltete Ressource (Token "wuppie") bleibt erhalten, da die noch von
192-
einem anderen Smartpointer verwaltet wird.
187+
einem anderen Smart-Pointer verwaltet wird.
193188

194-
Mit dem Ende der Funktion endet auch die Lebensdauer des Smartpointers `wuppie`. Er
195-
wird automatisch vom Stack entfernt, und da er im Beispiel der letzte Smartpointer
189+
Mit dem Ende der Funktion endet auch die Lebensdauer des Smart-Pointers `wuppie`. Er
190+
wird automatisch vom Stack entfernt, und da er im Beispiel der letzte Smart-Pointer
196191
ist, der das Token "wuppie" verwaltet, wird dabei automatisch der Pointer zu
197192
"wuppie" wieder freigegeben.
198193

199-
Ein Smartpointer soll entsprechend folgende Eigenschaften haben:
194+
Ein Smart-Pointer soll entsprechend folgende Eigenschaften haben:
200195

201196
- Verwendung soll analog zu normalen Pointern sein (Operatoren `*` und `->`
202197
überladen)
203-
- Smartpointer haben niemals einen undefinierten Wert: entweder sie zeigen auf ein
204-
Objekt oder auf `nullptr`[^3]
205-
- Kopieren von (*shared*) Smartpointern führt dazu, dass sich mehrere Smartpointer
206-
das verwiesene Objekt *teilen*
207-
- Smartpointer löschen sich selbst (und das verwiesene Objekt, falls kein anderer
208-
Smartpointer mehr darauf zeigt), wenn die Smartpointer ungültig werden (bei
198+
- Smart-Pointer haben niemals einen undefinierten Wert: entweder sie zeigen auf
199+
ein Objekt oder auf `nullptr`[^3]
200+
- Kopieren von (*shared*) Smart-Pointern führt dazu, dass sich mehrere
201+
Smart-Pointer das verwiesene Objekt *teilen*
202+
- Smart-Pointer löschen sich selbst (und das verwiesene Objekt, falls kein anderer
203+
Smart-Pointer mehr darauf zeigt), wenn die Smart-Pointer ungültig werden (bei
209204
Verlassen des Scopes bzw. bei explizitem Aufruf von `delete` auf einen Pointer
210-
auf einen Smartpointer)
211-
- Es gibt keine verwitweten Objekte mehr: Wenn mehrere Smartpointer auf das selbe
212-
Objekt zeigen, darf erst der letzte Smartpointer das Objekt aus dem Heap löschen
213-
- Smartpointer funktionieren nur für mit `new` erzeugte Objekte
205+
auf einen Smart-Pointer)
206+
- Es gibt keine verwitweten Objekte mehr: Wenn mehrere Smart-Pointer auf das selbe
207+
Objekt zeigen, darf erst der letzte Smart-Pointer das Objekt aus dem Heap
208+
löschen
209+
- Smart-Pointer funktionieren nur für mit `new` erzeugte Objekte
214210

215211
Weitere übliche Eigenschaften, die wir auf diesem Blatt aber vereinfachend
216212
ignorieren[^4]:
217213

218-
- Smartpointer sollen für beliebige Klassen nutzbar sein (Template-Klasse)
219-
- Dereferenzierung von nicht existierenden Objekten (d.h. der Smartpointer zeigt
214+
- Smart-Pointer sollen für beliebige Klassen nutzbar sein (Template-Klasse)
215+
- Dereferenzierung von nicht existierenden Objekten (d.h. der Smart-Pointer zeigt
220216
intern auf `nullptr`) führt nicht zum Programmabsturz, sondern zu einer
221217
Exception
222218

223219
## Reference Counting
224220

225-
Smartpointer werden erzeugt, indem sie entweder einen Pointer auf die zu verwaltende
226-
Ressource bekommen (Konstruktor) oder eine Referenz auf ein anderes
227-
Smartpointer-Objekt (Copy-Konstruktor).
221+
Smart-Pointer werden erzeugt, indem sie entweder einen Pointer auf die zu
222+
verwaltende Ressource bekommen (Konstruktor) oder eine Referenz auf ein anderes
223+
Smart-Pointer-Objekt (Copy-Konstruktor).
228224

229-
Im Smartpointer wird entsprechend der Pointer auf die zu verwaltende Ressource
225+
Im Smart-Pointer wird entsprechend der Pointer auf die zu verwaltende Ressource
230226
gespeichert.
231227

232-
Für die Bestimmung, wie viele Smartpointer sich eine Ressource teilen, muss ein
233-
Zähler implementiert werden. Sobald sich ein weiterer Smartpointer die selbe
228+
Für die Bestimmung, wie viele Smart-Pointer sich eine Ressource teilen, muss ein
229+
Zähler implementiert werden. Sobald sich ein weiterer Smart-Pointer die selbe
234230
Ressource teilt, muss dort auch der Zähler (per Pointer!) übernommen werden und
235231
entsprechend inkrementiert werden. Im Destruktor muss der Zähler dekrementiert
236232
werden. Falls dabei der Zähler den Wert 0 erreicht, werden die Pointer auf die
@@ -317,13 +313,13 @@ private:
317313
};
318314
```
319315
320-
## Dereferenzierung von Smartpointern
316+
## Dereferenzierung von Smart-Pointern
321317
322318
(*Anmerkung*: Dies ist ein Vorgriff auf die Lektion "Operatoren". Betrachten und
323319
implementieren Sie die vorgegebenen Operatoren einfach wie normale Methoden.)
324320
325321
Pointer lassen sich dereferenzieren, d.h. man greift direkt auf das verwiesene
326-
Objekt zu. Dies lässt sich auch für Smartpointer erreichen, indem die beiden
322+
Objekt zu. Dies lässt sich auch für Smart-Pointer erreichen, indem die beiden
327323
Dereferenzierungsoperatoren überladen werden.
328324
329325
``` cpp
@@ -346,7 +342,7 @@ public:
346342
```
347343

348344
Damit lässt sich das folgende Verhalten realisieren (Vergleich *raw* Pointer
349-
vs. Smartpointer):
345+
vs. Smart-Pointer):
350346

351347
``` cpp
352348
Token* foo = new Token("foo", 9, 35); // raw pointer foo
@@ -423,9 +419,9 @@ hier können Sie bei Bedarf zusätzliche Attribute und Methoden hinzufügen.
423419
424420
Testen Sie Ihre `RefCounter`-Klasse an selbst gewählten Beispielen.
425421
426-
## A7.4: Smartpointer (3P)
422+
## A7.4: Smart-Pointer (3P)
427423
428-
Implementieren Sie nun die Smartpointer für `Token`-Objekte mit folgender Signatur
424+
Implementieren Sie nun die Smart-Pointer für `Token`-Objekte mit folgender Signatur
429425
(wie oben, leicht erweitert):
430426
431427
``` cpp
@@ -518,10 +514,10 @@ Attribut `head` merkt man sich stattdessen, wo das nächste zu lesende Element l
518514
gewordenen Platz im internen Array `elems` eingefügt.
519515

520516
Unser Ringpuffer ist auf Elemente vom Typ `SmartToken` festgelegt. Es wird davon
521-
ausgegangen, dass diese Elemente Smartpointer mit der *shared pointer*-Semantik
517+
ausgegangen, dass diese Elemente Smart-Pointer mit der *shared pointer*-Semantik
522518
sind.[^5] Da die `SmartToken` selbst (zum Teil) eine Pointersemantik implementiert
523-
haben (man kann die Smartpointer dereferenzieren), vermeiden wir Pointer auf die
524-
Smartpointer in der Schnittstelle und arbeiten stattdessen mit C++-Referenzen bzw.
519+
haben (man kann die Smart-Pointer dereferenzieren), vermeiden wir Pointer auf die
520+
Smart-Pointer in der Schnittstelle und arbeiten stattdessen mit C++-Referenzen bzw.
525521
Kopien: Bei `writeBuffer()` wird ein `SmartToken` per konstanter C++-Referenz
526522
übergeben, und bei `readBuffer()` wird eine Kopie des gelesenen `SmartToken`
527523
zurückgeliefert.
@@ -590,8 +586,8 @@ Bei Bedarf können Sie zusätzliche Attribute und Methoden hinzufügen.
590586
591587
Testen Sie Ihre `RingBuffer`-Klasse an selbst gewählten Beispielen. Überzeugen Sie
592588
sich insbesondere vom korrekten Zugriff auf die Ringstruktur und prüfen Sie, ob die
593-
Smartpointer wie gewünscht arbeiten. Prüfen Sie hierzu auch die `RefCounter` der
594-
beteiligten Smartpointer. Welche Sonderfälle können Sie identifizieren?
589+
Smart-Pointer wie gewünscht arbeiten. Prüfen Sie hierzu auch die `RefCounter` der
590+
beteiligten Smart-Pointer. Welche Sonderfälle können Sie identifizieren?
595591
596592
[^1]: Anmerkung: Man spricht trotzdem von "Freigabe" des Objekts, obwohl lediglich
597593
der Stackpointer zurückgesetzt wird und das Objekt zunächst auf dem Stack noch
@@ -611,4 +607,3 @@ beteiligten Smartpointer. Welche Sonderfälle können Sie identifizieren?
611607
612608
[^5]: Wenn Sie die obigen Aufgaben richtig gelöst haben, haben Sie genau diese
613609
Semantik vorliegen.
614-
-->

0 commit comments

Comments
 (0)