#include <iostream>

using namespace std;

class BankAccount
{
public:
   BankAccount();
   void deposit(int amount);
   int get_balance() const;
private:
   int balance;
};

BankAccount::BankAccount()
   : balance(0)
{}

void BankAccount::deposit(int amount)
{
   balance = balance + amount;
}

int BankAccount::get_balance() const
{
   return balance;
}

int main()
{

   // We allocate a BankAccount object and have two pointers
   // to it

   BankAccount* harrys_account = new BankAccount();
   BankAccount* sallys_account = harrys_account;

   // We use the first pointer to deposit money into the
   // account. Looking up the balance through the second pointer
   // shows the correct balance

   harrys_account->deposit(10000);
   cout << "Before delete: " << sallys_account->get_balance() << endl;
   
   // Now we delete the first pointer and "to be safe" even set
   // the pointer variable to 0 (a common recommendation)

   delete harrys_account;
   harrys_account = 0;
   
   // However, there is still a second pointer to the object
   // Accessing the deleted object through the second pointer
   // yields a surprising result

   cout << "After delete: " << sallys_account->get_balance() << endl;
   return 0;
}

/*

Output:

Before delete: 10000
After delete: 1627889916 (you may get a different value when
running this program)

Explanation:

Most free store implementations reuse some of the space in
deallocated memory blocks to manage a list of free blocks. 
Immediately when the block is freed, a link is stored in the
block, overwriting some of the memory contents (which the 
programmer presumably no longer needs). 

*/

