временный и копирующий конструктор - PullRequest
2 голосов
/ 19 декабря 2010

В приведенной ниже программе я попытался поэкспериментировать с копирующим ctor, есть один момент, который неясен, когда функция f( ) возвращает его, следует использовать copy-ctor для создания нового объекта для h2, однакоЯ предполагаю, что это достигается временным объектом, который использует конструктор объекта, а затем делает копию, однако вывод уничтожения показывает, что я ошибаюсь в этом рассуждении ... некоторые разъяснения приветствуются по этой проблеме;)

#include <fstream>
#include <string>
using namespace std;
ofstream out("HowMany2.out");

class HowMany2 {
  string name; // Object identifier
  static int objectCount;
public:
  HowMany2(const string& id = "") : name(id) {
    ++objectCount;
    print("HowMany2()");
  }
  ~HowMany2() {
    --objectCount;
    print("~HowMany2()");
  }
  // The copy-constructor:
  HowMany2(const HowMany2& h) : name(h.name) {
    name += " copy";
    ++objectCount;
    print("HowMany2(const HowMany2&)");
  }
  void print(const string& msg = "") const {
    if(msg.size() != 0) 
      out << msg << endl;
    out << '\t' << name << ": "
        << "objectCount = "
        << objectCount << endl;
  }
};

int HowMany2::objectCount = 0;

// Pass and return BY VALUE:
HowMany2 f(HowMany2 x) {
  x.print("x argument inside f()");
  out << "Returning from f()" << endl;
  return x;
}

int main() {
  HowMany2 h("h");
  out << "Entering f()" << endl;
  HowMany2 h2 = f(h);
} 

Выход

HowMany2()
  h: objectCount = 1
Entering f()
HowMany2(const HowMany2&)
  h copy: objectCount = 2
x argument inside f()
  h copy: objectCount = 2
Returning from f()
HowMany2(const HowMany2&)
  h copy copy: objectCount = 3
~HowMany2()
  h copy: objectCount = 2  // Confused here !!!! why not h copy copy
~HowMany2()
  h copy copy: objectCount = 1
~HowMany2()
  h: objectCount = 0

Ответы [ 3 ]

2 голосов
/ 19 декабря 2010

h copy copy в основном h2 из этой строки:

HowMany2 h2 = f(h);

Он разрушается при выходе из main.

h copy - аргумент f, он разрушается, когда f возвращается.Поскольку f возвращается до main, h copy уничтожается до h copy copy.

Обратите внимание, что RVO (оптимизация возвращаемого значения) была выполнена компилятором.В этом коде нет созданных временных файлов.На самом деле этот код может выводить разные результаты в зависимости от компилятора.Компилятор может делать 1 или 2 вызова конструктора копирования в этом коде.(Возможно, в этом случае также возможен ноль, хотя я не знаю, как это оправдать.)

Редактировать: Ваш код реализован таким компилятором (псевдокод):

void f(HowMany2 *result, HowMany2* xptr) {
  HowMany2 x(*xptr); // local copy

  x.print("x argument inside f()");
  out << "Returning from f()" << endl;

  new(result) HowMany2(x); // copy the return value

  x.~HowMany(); // destroy local copy
}

int main() {
  HowMany2 h("h");
  out << "Entering f()" << endl;
  HowMany2 h2; // not initialized
  f(&h2, &h);
  h2.~HowMany2();
} 
1 голос
/ 19 декабря 2010

В этой точке «путаницы» временный локальный объект функции f уничтожается («h copy») после того, как он был возвращен для создания копии вне функции («h copy copy»).Затем объекты вне функции уничтожаются в обратном порядке их создания: скопированный объект («h copy copy») и, наконец, исходный объект («h»).

0 голосов
/ 19 декабря 2010

Возвращаемое значение из f () выполняет конструкцию копирования обратно в main.
Результат помещает значение в переменную h2.

Таким образом, параметр x в функции уничтожается первым (так как он покидает функцию).
Затем h2, затем h при выходе из основной функции и ее локальных переменных.

~HowMany2()
  h copy: objectCount = 2          // destruction of x
~HowMany2()
  h copy copy: objectCount = 1     // destruction of h2
~HowMany2()
  h: objectCount = 0               // festruction of h

Если ты хочешь быть действительно взволнованным. Включите оптимизацию до полного -O3 на gcc или выполните сборку в режиме выпуска в VisStudio. Посмотрите, как выходные данные отличаются.

...