Бьерн Страуструп - Язык программирования С++. Главы 5-7 - Локальные переменные

ОГЛАВЛЕНИЕ

5.5.1 Локальные переменные

Конструктор локальной переменной вызывается каждый раз, когда при выполнении программы встречается ее описание. Деструктор локальной переменной вызывается всякий раз по выходе из блока, где она была описана. Деструкторы для локальных переменных вызываются в порядке, обратном вызову конструкторов при их создании:
          void f(int i)
          {
            table aa;
            table bb;
            if (i>0) {
                table cc;
                // ...
            }
            // ...
          }
Здесь aa и bb создаются (именно в таком порядке) при каждом вызове f(), а уничтожаются они при возврате из f() в обратном порядке - bb, затем aa. Если в текущем вызове f() i больше нуля, то cc создается после bb и уничтожается прежде него.

Поскольку aa и bb - объекты класса table, присваивание aa=bb означает копирование по членам bb в aa (см. $$2.3.8). Такая интерпретация присваивания может привести к неожиданному (и обычно нежелательному) результату, если присваиваются объекты класса, в котором определен конструктор:

           void h()
           {
              table t1(100);
              table t2 = t1;   // неприятность
              table t3(200);

              t3 = t2;         // неприятность
           }
В этом примере конструктор table вызывается дважды: для t1 и t3. Он не вызывается для t2, поскольку этот объект инициализируется присваиванием. Тем не менее, деструктор для table вызывается три раза: для t1, t2 и t3! Далее, стандартная интерпретация присваивания - это копирование по членам, поэтому перед выходом из h() t1, t2 и t3 будут содержать указатель на массив имен, память для которого была выделена в свободной памяти при создании t1. Указатель на память, выделенную для массива имен при создании t3, будет потерян. Этих неприятностей можно избежать (см. $$1.4.2 и $$7.6).