Wissensspeicher 9

Gültigkeitsbereiche

  • Bisher: Variablen sind innerhalb eines Blocks sichtbar
  • Neu: Globale Variablen
    • … werden außerhalb der Funktionen deklariert (und bitte initialisiert)
    • … sind ab Deklaration im weiteren C++-Code sichtbar
  • Neu: Namensüberdeckung
    • Variablen gleichen Namens innerhalb eines Blocks überdecken äußere Variablen
    • Am Ende eines Blocks endet die Sichtbarkeit (und ggf. die Existenz) einer inneren Variablen
    • Zugriff auf globale Variablen mit scope resolution operator :: jeder Zeit möglich
    • Sorgt nicht selten für Verwirrung → Bitte vermeidet Namensüberdeckungen

pages/Kapitel07-page-01.svg

pages/Kapitel07-page-02.svg

pages/Kapitel07-page-03.svg

pages/Kapitel07-page-04.svg

pages/Kapitel07-page-05.svg

pages/Kapitel07-page-06.svg

pages/Kapitel07-page-07.svg

pages/Kapitel07-page-08.svg

pages/Kapitel07-page-09.svg

pages/Kapitel07-page-10.svg

pages/Kapitel07-page-11.svg

pages/Kapitel07-page-12.svg

pages/Kapitel07-page-13.svg

pages/Kapitel07-page-14.svg

pages/Kapitel07-page-15.svg

pages/Kapitel07-page-16.svg

pages/Kapitel07-page-17.svg

pages/Kapitel07-page-18.svg

pages/Kapitel07-page-19.svg

pages/Kapitel07-page-20.svg

pages/Kapitel07-page-21.svg

pages/Kapitel07-page-22.svg

pages/Kapitel07-page-23.svg

Live-Demo - Fakultät

#include <iostream>
#include <chrono>

using namespace std;
using namespace std::chrono;

long fakultaet(int n) {
    if (n == 0) return 1;         // Rekursionsverankerung
    return n * fakultaet(n - 1);  // Rekursionsschritt
}

int main() {
    int n = 10;
    cout << n << "! = " << fakultaet(n) << endl;
    n = 100000;
    long f;
    time_point<steady_clock> jetzt = steady_clock::now();
    f = fakultaet(n);
    time_point<steady_clock> spaeter = steady_clock::now();
    duration<double> zeit = spaeter - jetzt;

    cout << n << "! = " << f << endl;
    cout << "Zeit rekursiv: " << zeit.count() << " sec." << endl;
	return 0;
}
compiler

pages/Kapitel07-page-24.svg

pages/Kapitel07-page-25.svg

pages/Kapitel07-page-26.svg

pages/Kapitel07-page-27.svg

pages/Kapitel07-page-28.svg

pages/Kapitel07-page-29.svg

pages/Kapitel07-page-30.svg

pages/Kapitel07-page-31.svg

pages/Kapitel07-page-32.svg

pages/Kapitel07-page-33.svg

pages/Kapitel07-page-34.svg

pages/Kapitel07-page-35.svg

pages/Kapitel07-page-36.svg

pages/Kapitel07-page-37.svg

pages/Kapitel07-page-38.svg

pages/Kapitel07-page-39.svg

pages/Kapitel07-page-40.svg

pages/Kapitel07-page-41.svg

pages/Kapitel07-page-42.svg

pages/Kapitel07-page-43.svg

pages/Kapitel07-page-44.svg

pages/Kapitel07-page-45.svg

pages/Kapitel07-page-46.svg

pages/Kapitel07-page-47.svg

pages/Kapitel07-page-48.svg

pages/Kapitel07-page-49.svg

pages/Kapitel07-page-50.svg

pages/Kapitel07-page-51.svg

pages/Kapitel07-page-52.svg

pages/Kapitel07-page-53.svg

pages/Kapitel07-page-54.svg

pages/Kapitel07-page-55.svg

pages/Kapitel07-page-56.svg

pages/Kapitel07-page-57.svg

pages/Kapitel07-page-58.svg

pages/Kapitel07-page-59.svg

pages/Kapitel07-page-60.svg

pages/Kapitel07-page-61.svg

pages/Kapitel07-page-62.svg

pages/Kapitel07-page-63.svg

pages/Kapitel07-page-64.svg

pages/Kapitel07-page-65.svg

pages/Kapitel07-page-66.svg

pages/Kapitel07-page-67.svg

pages/Kapitel07-page-68.svg

pages/Kapitel07-page-69.svg

pages/Kapitel07-page-70.svg

pages/Kapitel07-page-71.svg

pages/Kapitel07-page-72.svg

pages/Kapitel07-page-73.svg

pages/Kapitel07-page-74.svg

pages/Kapitel07-page-75.svg

pages/Kapitel07-page-76.svg

pages/Kapitel07-page-77.svg

pages/Kapitel07-page-78.svg

pages/Kapitel07-page-79.svg

pages/Kapitel07-page-80.svg

pages/Kapitel07-page-81.svg

pages/Kapitel07-page-82.svg

pages/Kapitel07-page-83.svg

pages/Kapitel07-page-84.svg

pages/Kapitel07-page-85.svg

pages/Kapitel07-page-86.svg

pages/Kapitel07-page-87.svg

pages/Kapitel07-page-88.svg

pages/Kapitel07-page-89.svg

pages/Kapitel07-page-90.svg

pages/Kapitel07-page-91.svg

pages/Kapitel07-page-92.svg

pages/Kapitel07-page-93.svg

pages/Kapitel07-page-94.svg

pages/Kapitel07-page-95.svg

pages/Kapitel07-page-96.svg

pages/Kapitel07-page-97.svg

pages/Kapitel07-page-98.svg

pages/Kapitel07-page-99.svg

pages/Kapitel07-page-100.svg

pages/Kapitel07-page-101.svg

pages/Kapitel07-page-102.svg

pages/Kapitel07-page-103.svg

pages/Kapitel07-page-104.svg

pages/Kapitel07-page-105.svg

pages/Kapitel07-page-106.svg

Live-Demo - Fakultät rekursiv vs. iterativ

#include <iostream>
#include <chrono>

using namespace std;
using namespace std::chrono;

long fakultaet(int n) {
	if (n == 0) return 1;         // Rekursionsverankerung
	return n * fakultaet(n - 1);  // Rekursionsschritt
}

long long fakultaetIter(int n) {
	long wert = 1;
	while (n > 0) wert *= n--;
	return wert;
}

int main() {
	int n = 10;
	cout << n << "!=" << fakultaet(n) << endl;

	n = 20;
	cout << n << "!=" << fakultaet(n) << endl;

	n = 100000;
	long f;
	time_point<steady_clock> jetzt = steady_clock::now();
	f = fakultaet(n);
	time_point<steady_clock> spaeter = steady_clock::now();
	duration<double> zeit = spaeter - jetzt;

	cout << f << endl;
	cout << "Zeit rekursiv: " << zeit.count() << " sec." << endl;

	jetzt = steady_clock::now();
	f = fakultaetIter(n);
	spaeter = steady_clock::now();
	zeit = spaeter - jetzt;

	cout << f << endl;
	cout << "Zeit iterativ: " << zeit.count() << " sec." << endl;

    return 0;
}
compiler

pages/Kapitel07-page-107.svg

pages/Kapitel07-page-108.svg

pages/Kapitel07-page-109.svg

pages/Kapitel07-page-110.svg

pages/Kapitel07-page-111.svg

pages/Kapitel07-page-112.svg

pages/Kapitel07-page-113.svg

Live-Demo - Anzahl rekursiver Aufrufe

#include <iostream>

using namespace std;

// Anzahl rekursiver Aufrufe, wenn die Funktion
// sich genau einmal selber aufruft
int rekursiv1(int n) {
    if (n == 1) return 1;
    int a;
    a = rekursiv1(n - 1);
    return a + 1;
}

// Anzahl rekursiver Aufrufe, wenn die Funktion
// sich genau zweimal selber aufruft
int rekursiv2(int n) {
    if (n == 1) return 1;
    int a, b;
    a = rekursiv2(n - 1);
    b = rekursiv2(n - 1);
    return a + b + 1;
}

// Anzahl rekursiver Aufrufe, wenn die Funktion
// sich genau dreimal selber aufruft
int rekursiv3(int n) {
    if (n == 1) return 1;
    int a, b, c;
    a = rekursiv3(n - 1);
    b = rekursiv3(n - 1);
    c = rekursiv3(n - 1);
    return a + b + c + 1;
}

// Anzahl lokaler Variablen bei 2 rekursiven
// Aufrufen und 3 Parametern
// (die Variablen a und b sind nur für die Berechnung
//  und werden nicht mitgezählt)
int rekursiv23(int n, int li, int re) {
    if (n == 1) return 3;
    int a, b;
    a = rekursiv23(n - 1, li, re);
    b = rekursiv23(n - 1, li, re);
    return a + b + 3;
}

int main() {
    cout << "rekursiv1(10) : " << rekursiv1(10) << endl;
    cout << "rekursiv2(10) : " << rekursiv2(10) << endl;

    cout << "------" << endl;
    for (int i = 1; i <= 20; ++i) {
        cout << i << " : " << rekursiv2(i) << endl;
    }
    cout << "------" << endl;
    for (int i = 1; i <= 10; ++i) {
        cout << i << " : " << rekursiv3(i) << endl;
    }
    cout << "------" << endl;

    cout << "rekursiv23(10) : " << rekursiv23(10, 1, 1) << endl;
    cout << "rekursiv23(20) : " << rekursiv23(20, 1, 1) << endl;

    return 0;
}
compiler

Warum ist eine große Zahl an rekursiven Aufrufen gefährlich?

// Anzahl rekursiver Aufrufe, wenn die Funktion
// sich genau dreimal selber aufruft
int rekursiv3(int n) {
    if (n == 1) return 1;
    int a, b, c;
    a = rekursiv3(n - 1);
    b = rekursiv3(n - 1);
    c = rekursiv3(n - 1);
    return a + b + c + 1;
}
  • Pro Aufruf werden drei Variablen auf dem Stack abgelegt
  • Pro Aufruf werden drei weitere Aufrufe erzeugt
  • Für große n gibt es dementsprechend viele rekursive Aufrufe

→ Mit jedem Aufruf verdreifacht sich die Anzahl der Variablen auf dem Stack

→ 🚨 Gefahr 🚨 eines Stacküberlaufs

gen/memory-layout-crop.svg