Где вызывается конструктор копирования?

#c #g #copy-constructor

#c #g #копировать-конструктор

Вопрос:

Я написал небольшой фрагмент кода на C в main.cpp файл и я пытаюсь понять, как это работает.

Сначала я определил класс «Значение».:

 #include <algorithm>
#include <iostream>

using namespace std;

class Value {

  int v;

 public:

  Value(int v): v(v) {
    cout << "Ctor called" << endl;
  }

  Value(const Value amp;rhs): v(rhs.v) {
    cout << "Copy Ctor called. V = " << v << endl;
  }

  Valueamp; operator =(const Value amp;rhs) {
    cout << "Assignment called" << endl;
    if (this != amp;rhs) {
      auto tmp = Value(rhs);
      swap(v, tmp.v);
    }
    return *this;
  }

  int rawValue() const {
    return v;
  }

};
 

Затем я выполнил main:

 Value doubleValue(const Value amp;v) {
  auto newValue = Value(v.rawValue() * 2);
  return newValue;
}

int main() {
  cout << "Creating v = 10" << endl;
  auto v = Value(10);

  cout << "Creating v = 20" << endl;
  auto v2 = doubleValue(v);

  return 0;
}
 

Я использую g в качестве своего компилятора, и когда я запускаю следующий код:

 g   --std=c  11 -fno-elide-constructors -c main.cpp
g   main.o -o main.exe
./main.exe
 

Который выводит следующее:

 Creating v = 10
Ctor called
Creating v = 20
Ctor called
 

Я снова компилирую код, но без оптимизации конструкторов копирования:

 g   --std=c  11 -fno-elide-constructors -c main.cpp
g   main.o -o main.exe
./main.exe
 

И теперь он выводит следующее:

 Creating v = 10
Ctor called
Copy Ctor called. V = 10
Creating v = 20
Ctor called
Copy Ctor called. V = 20
Copy Ctor called. V = 20
Copy Ctor called. V = 20
 

Не уверен, почему он вызывает конструктор копирования так много раз. Я новичок в C и хотел бы лучше понять процесс. Мне любопытно узнать, как выполняется этот код и почему конструктор копирования вызывается так часто.

Ответ №1:

Вот копии:

  • auto v = Value(10); инициализируется v с помощью copy-constructor from Value(10) .
  • auto newValue = Value(v.rawValue() * 2); инициализируется newValue с помощью copy-constructor from Value(v.rawValue()*2) .
  • return newValue; инициализирует возвращаемое значение с помощью copy-constructor from newValue .
  • auto v2 = doubleValue(v); инициализируется v2 с помощью copy-constructor из возвращаемого значения.

Все это контексты копирования-исключения.

Ответ №2:

Прочитайте об оптимизации возвращаемого значения (RVO). Если RVO отключен, то ваш конструктор копирования вызывается очень часто. Если включен RVO, то, например, код auto v = Value(10); пропускает вызовы copy ctor.