Сколько раз вызывается конструктор - PullRequest
0 голосов
/ 10 января 2019

Допустим, у нас есть класс Custom String, который выглядит следующим образом

using namespace std;

class CustomStr {
public:
  const char* s;

  // converting constructor
  CustomStr(const char* s) : s (s) {
    cout << "Constructor called" << endl;
  }

  // Copy constructor    
  CustomStr(const CustomStr& cs) : s (cs.s) {
    cout << "Copy Constructor called" << endl;
  }
};

Давайте рассмотрим следующий код:

int main() {
  CustomStr cs("Some char pointer");
  CustomStr cs_copy = cs;
  return 0;
}

В вышеприведенном случае мы ожидаем, что сначала будет вызван конвертирующий конструктор, а после этого будет вызван конструктор копирования для CustomStr cs_copy = cs, и мы получим соответствующий вывод, как и ожидалось

$ ./a.out
Constructor called
Copy Constructor called

Теперь рассмотрим следующий код

int main() {
  CustomStr cs_copy = CustomStr("Some char pointer");
  return 0;
}

В этом случае я также подумал, что нужно сделать 2 вызова конструктора - преобразовать вызов конструктора для CustomStr("Some char pointer") и скопировать вызов конструктора для CustomStr cs_copy = CustomStr("Some char pointer"). Но вывод показывает только вызываемый конструктор преобразования.

Я не смог объяснить, как это происходило. Я ожидал, что компилятор оптимизирует работу, но я хотел понять, в каких случаях эта оптимизация запускается.

Ответы [ 2 ]

0 голосов
/ 10 января 2019

Поскольку C ++ 17, T x = T(A); определено так же, как: T x(A);. (где A - любой, возможно, пустой, список выражений, а MVP отсутствует).

До C ++ 17 компилятору было разрешено выбирать, обрабатывать ли код как T x(A); или создавать временный, а затем копировать / перемещать конструкцию x из временного.

0 голосов
/ 10 января 2019

Цитата из cppreference :

если инициализатор является выражением prvalue, тип которого совпадает с классом T (игнорируя квалификацию cv), то для инициализации целевого объекта используется само выражение инициализатора, а не временное материализованное из него значение

CustomStr("Some char pointer") - это значение того же типа, что и cs_copy. Поэтому нет ни временной, ни копии. cs_copy просто напрямую инициализируется из этого выражения.

До C ++ 17 раньше, когда речь шла об абстрактной машине, был временный объект, но стандарт не требует вызова конструктора копирования, и, следовательно, такое же поведение, как и у C ++ 17 было разрешено в качестве оптимизации. Более подробная информация на cppreference: copy elision .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...