/*
 * Lösung für Übung 9.6.2 - Zeigerfehler
 * Diese Datei enthält drei Teile:
 * - Den auskommentierten fehlerhaften Code
 * - Eine Korrektur mittels normaler Zeiger
 * - Eine Korrektur mit Smart Pointern
 */
#include <iostream>
#include <string>
#include <memory>

int main()
{
  /* FEHLERHAFTER CODE:
  
  std::string* stringPointer;
  bool* consoleOutput = new bool(false);
  int* intPointer = new int(0);
  if (consoleOutput)
  {
    std::cout << "consoleOutput ist wahr" << std::endl;
  }
  intPointer = 17;
  if (intPointer + 1 == 18)
  {
    bool otherValue = true;
    std::cout << "Diese Ausgabe sollte kommen";
    consoleOutput = &otherValue;
  }
  delete stringPointer;
  delete intPointer;

  */

  // Korrektur ohne Smart Pointer:
  {
    // Der Pointer war nicht auf nullptr initialisiert!
    // Das "delete stringPointer" später hätte zu einem riesen Problem geführt.
    // Völlig zufälliger Speicher wäre freigegeben worden
    std::string* stringPointer = nullptr;
    bool* consoleOutput = new bool(false);
    int* intPointer = new int(0);
    // Das Dereferenzieren (Sternchen) wurde vergessen. Ohne das Sternchen
    // war der Vergleich gleichbedeutend mit if (consoleOutput != nullptr) , was definitiv
    // nicht der hier beabsichtigte Vergleich war
    if (*consoleOutput)
    {
      std::cout << "consoleOutput ist wahr" << std::endl;
    }
    // Das Dereferenzieren des Zeigers wurde vergessen
    *intPointer = 17;
    // Hier ebenfalls.
    if (*intPointer + 1 == 18)
    {
      // Spitzfindigerweise könnte man sagen, hier fehle noch das std::endl. Ist aber nicht so wichtig.
      std::cout << "Diese Ausgabe sollte kommen" << std::endl;
      // Hier gab es zwei Probleme: Erstens wurde der Zeiger consoleOutput auf die Variable
      // otherValue umgebogen, die aber nach Verlassen des Bereichs ungültig wurde.
      // Zweitens muss vor dem Umbiegen des Zeigers auf einen neuen Speicherbereich der alte
      // erst mit delete aufgeräumt werden. Hier wurde das gemacht und danach dann mit new
      // ein neuer Speicherbereich belegt
      delete consoleOutput;
      consoleOutput = new bool(true);
    }
    // Das Aufräumen von consoleOutput fehlte
    delete intPointer;
    delete consoleOutput;
    // stringPointer ist zwar das ganze Programm hindurch nullptr geblieben,
    // zur Sicherheit räumen wir es aber trotzdem auf.
    delete stringPointer;
  }

  // Korrektur: mit Smart Pointern
  {
    std::shared_ptr<std::string> stringPointer;
    std::shared_ptr<bool> consoleOutput = std::make_shared<bool>(false);
    std::shared_ptr<int> intPointer = std::make_shared<int>(0);
    if (*consoleOutput)
    {
      std::cout << "consoleOutput ist wahr" << std::endl;
    }
    *intPointer = 17;
    if (*intPointer + 1 == 18)
    {
      std::cout << "Diese Ausgabe sollte kommen" << std::endl;
      // Kein vorheriges delete notwendig - wird automatisch erledigt.
      consoleOutput = std::make_shared<bool>(true);
    }
    // Keine delete Anweisungen notwendig - wird automatisch erledigt.
  }

  return 0;
}
