Ergänzungen

Initialisierung vs Zuweisung im Constructor

In bisherigen Beispielen wurde Member Variablen durch Zuweisung im Constructor initialisiert:


// Initialisierung durch assignment in constructor body
 My3Vector::My3Vector() { // default constructor
   x = 0.; y = 0.; z = 0.; // set coords to 0.
 }
 My3Vector::My3Vector( double c1, double c2, double c3 ) {
   x = c1; y = c2; z = c3; // take args for coords
 }

Alternativ direkte Initialisierung mit spezieller Syntax ausserhalb des "Constructor-Bodys":


// Direckte Initialisierung ausserhalb von constructor body
My3Vector::My3Vector() : x(0.), y(0.), z(0.)  // default constructor
{ }
My3Vector::My3Vector( double c1, double c2, double c3 ) :
x(c1), y(c2), z(c3)
{ } 
// bei Vererbung einzige Moeglichkeit Basisklassen--Konstruktor zu rufen
MyLVector::MyLVector(double c0, double c1, double c2, double c3) :
   My3Vector(c1, c2, c3), t(c0) // special initialization syntax
{}

In ThreeVector Beispiel ziemlich egal wie man es macht,
aber manchmal direkte Initialisierung erforderlich oder vorzuziehen:


this Pointer

Manchmal muss man in einer Member-Funktion explizit auf das Objekt verweisen oder zugreifen können,

dann expliziter Zugriff mit this: pointer auf Objekt. this ist immer automatisch deklariert.


// gleiche Namen fuer lokale Variablen und Member-variablen
 My3Vector::My3Vector( double x, double y, double z ) {
   this->x = x;  // Expliziter Zugriff auf member variable mit this
   this->y = y;  // x alleine ist lokale Variable (Funktionsargument)
   this->z = z;
 }


Gültigkeitsbereich von Variablen und Objekten

In C++ unterscheidet man den scope und die lifetime von Variablen.
scope: Wo ist ein Objekt bekannt ?




#include <iostream>
void tscope_1( );  // declaration
void tscope_2( );
int glob_a = 42;   // define a global variable
int main()
{
  double a = 3.14;
  cout << "glob_a " << glob_a << endl;
  cout << "main a " << a << endl;
  tscope_1( );
  tscope_2( );
  {
    int a = -999;  // override outside definition
    cout << "main in block: a " << a << endl;
  }
  cout << "main a " << a << endl;  // what happened to a ?
}
void tscope_1( ) 
{   
  cout << "tscope_1 glob_a " << glob_a << endl; // global variable is known
}
void tscope_2( ) {
  int glob_a = -1;  // override global variable
  cout << "tscope_2 glob_a " << glob_a << endl; // unless it's overridden
}




Lifetime: Wie lange `lebt' ein Objekt ?
Hängt von Art der Variablen ab: automatic, static, dynamic.
automatic
Default, von der Definition bis zum Ende des Blocks, bzw. während des Funktionsaufrufs.
   int a;
   double arr[100];

static
Von Anfang bis Ende des Programms mit static Keyword
   static int a;


dynamic
Dynamisches Anlegen und Löschen mit Keywords new und delete unter der Kontrolle des Programmierers.
   cin >>n; // Eingabe fuer n zur Laufzeit
   double * arr = new double[n];
   ThreeVector * tv = new ThreeVector( 1.0, -0.5, 0.7);

Beliebig grosse Arrays/Speicherbereiche können auf diese Weise zur Laufzeit angelegt werden.

Oft die einzige sinnvolle Möglichkeit Variablen oder Objekte über Funktionsgrenzen hinaus zu verwenden.


Nach Gebrauch wieder zurückgeben mit
   delete [] arr;
   delete tv;

Ansonsten Memory Leaks !



  for ( int i=0; i<100000; i++ ) {
    double *p = new double[200000];
    ....    
  } // ohne delete [] p werden hier 20 GB benoetigt ...


Großes Problem bei komplexen C++ Software Projekten !




void tc1( );
void tc2( );
int main()
{ // demonstrate automatic, static, dynamic
  for ( int i=0; i<3; i++ ) {
    tc1();
    tc2();   }
  int * ap1 = new int[10];  // neuer int array mit 10 Elem.
  ap1[8] = 99;
  cout << "ap1[8] " << ap1[8] << endl;
  int * ap2 = new int(10);  // Vorsicht, [] vs (); hier 1 int mit Wert 10
  cout << "ap2[0] " << ap2[0] << endl;
  // Loeschen nicht vergessen;
  delete [] ap1;  // Wichtig: bei new ..[] auch delete []
  delete ap2;     //   sonst nur delete 
  // delete muss innerhalb des Blocks erfolgen, sonst pointer weg, 
  // aber nicht der allozierte Speicher !!
}
void tc1(  ) {
  int count = 0; // automatic counter
  count ++;
  cout << "tc1 " << count << endl; 
}
void tc2( ) {
  static int count = 0; // static counter
  count ++;
  cout << "tc2 " << count << endl; 
}




GDuckeck 2019-08-01