Open Source im professionellen Einsatz
Linux-Magazin 12/2012

Modernes C++ in der Praxis – Folge 7

Rasch verschoben

Diese Folge geht ans Eingemachte von C++11: Sie zeigt, wozu Move-Semantik nützlich ist, erklärt Rvalues und Lvalues und deckt auf, was es mit dem doppelten &-Zeichen auf sich hat.

568

Wenn das Kopieren von Daten zu aufwändig oder unmöglich ist, kann sich der Programmierer damit behelfen, sie stattdessen zu verschieben. Diese einfache Idee liegt der Move-Semantik in C++11 zugrunde. Wer sie geschickt anwendet, bewegt auf diese Weise große Datenmengen schneller und kann sogar Smart Pointer mit der STL versöhnen. Dieser Artikel zeigt, wie das geht.

Großer Kopierer

Listing 1 enthält eine einfache Klasse namens »BigArrayCopy« , die einen Wrapper um ein einfaches C-Array darstellt. Diese Programmzeilen sollen als Grundlage für weitere Optimierungen dienen. Um das C-Array richtig zu verwalten, merkt sich »BigArrayCopy« in den Zeilen 37 und 38 den Verweis auf das C-Array »data_« und dessen Länge »len_« .

Listing 1

Großes Array kopieren

01 #include <algorithm>
02 #include <iostream>
03 #include <vector>
04
05 using std::cout;
06 using std::endl;
07
08 using std::vector;
09
10 class BigArrayCopy{
11
12 public:
13   BigArrayCopy(size_t len): len_(len), data_(new int[len]){}
14
15   BigArrayCopy(const BigArrayCopy& other): len_(other.len_),data_(new int[other.len_]){
16     cout << "copy construction of " << other.len_ << " elements "<< endl;
17     std::copy(other.data_, other.data_ + len_, data_);
18    }
19
20   BigArrayCopy& operator=(const BigArrayCopy& other){
21      cout << "copy assignment of " << other.len_ << " elements "<< endl;
22      if (this != &other){
23         delete[] data_;
24
25         len_ = other.len_;
26         data_ = new int[len_];
27         std::copy(other.data_, other.data_ + len_, data_);
28      }
29      return *this;
30   }
31
32   ~BigArrayCopy(){
33      if (data_ != nullptr) delete[] data_;
34   }
35
36 private:
37   size_t len_;
38   int* data_;
39 };
40
41 int main(){
42
43   cout << endl;
44
45   vector<BigArrayCopy> myVec;
46
47   BigArrayCopy bArray(11111111);
48   BigArrayCopy bArray2(bArray);
49   myVec.push_back(bArray);
50
51   bArray= BigArrayCopy(22222222);
52   myVec.push_back(BigArrayCopy(33333333));
53
54   cout << endl;
55
56 }

Das Interface von »BigArrayCopy« ist minimal. Es besteht aus einem Standardkonstruktor (Zeile 13), einem Kopierkonstruktor (Zeile 15), einem Zuweisungsoperator (Zeile 20) und einem Destruktor (Zeile 32). Im Kopierkonstruktor, der sich durch den Aufruf »BigArrayCopy bArray2(bArray)« anstoßen lässt, setzt der Code die Länge und den Verweis auf das C-Array. Im Anschluss findet durch

std::copy(other.data_, other.data_ + len_,data_)

das Kopieren der Daten von »bArray« nach »bArray2« statt. Einer ähnlichen Struktur folgt der Zuweisungsoperator, der in dem Ausdruck »bArray= BigArrayCopy(22222222)« zur Anwendung kommt. Hier stellt in Zeile 42 die Klausel »if (this != &other)« sicher, dass Quelle und Ziel der Zuweisung verschieden sind. Das ist notwendig, denn Zeile 23 löscht das Ziel der Zuweisung mit »delete[] data_« . Das Ergebnis des Zuweisungsoperators ist das modifizierte Objekt, in Zeile 29 durch »return *this« zurückgegeben. Der Destruktor komplementiert den C-Array-Wrapper »BigArrayCopy« .

STL-tauglich

Mit diesem einfachen Interface erfüllt »BigArrayCopy« alle Anforderungen, damit es sich in einem Container der Standard Template Library (STL) verwenden lässt. Ein kleines C++11-Feature hat sich noch im Destruktor versteckt: »nullptr« ersetzt die bekannte Nullzeigerkonstante »NULL« . Damit gehört das implizite Konvertieren von »NULL« in eine natürliche Zahl der Vergangenheit an.

Wer das Programm ausführt und die Ausgabe betrachtet (Abbildung 1), der erkennt, dass sowohl der Kopierkonstruktor als auch der Zuweisungsoperator zum Einsatz kommen. Darüber hinaus lässt sich »BigArrayCopy« in einem Vektor verwenden. »BigArrayCopy« erfüllt offenbar alle Erwartungen.

Abbildung 1: Das herkömmliche Kopieren von BigArrayCopy ist aufwändig.

Diesen Artikel als PDF kaufen

Express-Kauf als PDF

Umfang: 5 Heftseiten

Preis € 0,99
(inkl. 19% MwSt.)

Linux-Magazin kaufen

Einzelne Ausgabe
 
Abonnements
 
TABLET & SMARTPHONE APPS
Bald erhältlich
Get it on Google Play

Deutschland

Ähnliche Artikel

  • C++11

    C++-Code sicherer machen und zugleich an der Performance-Schraube drehen, das sind die beiden Domänen der neuen Type-Traits-Bibliothek. Sie beschleunigt Code, indem sie Typen zur Kompilierzeit analysiert und verändert, wenn der Entwickler sie geschickt einsetzt.

  • C++

    Mit der Move-Semantik und konstanten Ausdrücken besitzt modernes C++ eine kräftige Stellschraube, um die Performance einer C++-Anwendung in die richtige Richtung zu drehen.

  • Erfrischend neu

    An der Sprache C++ ändert sich selten etwas. Doch nun steht mit dem C++0x ein neuer Standard vor der Tür, von dem Neulinge wie Könner profitieren sollen. Mit Move-Semantik, Lambda-Funktionen und Aggregatzuweisungen bringt er viele Modernisierungen in die Programmiersprache.

  • C++11

    In C++11 lässt sich manches prägnanter formulieren als in klassischem C++. Dieser Artikel zeigt, wie die neue Range-basierte For-Schleife und die automatische Typableitung dabei helfen.

  • C++11

    Der C++-Compiler erzeugt einige Methoden automatisch. In C++11 kann der Programmierer das gezielt steuern, indem er eine Reihe deklarativer Schlüsselwörter verwendet.

comments powered by Disqus

Ausgabe 10/2017

Digitale Ausgabe: Preis € 6,40
(inkl. 19% MwSt.)

Artikelserien und interessante Workshops aus dem Magazin können Sie hier als Bundle erwerben.