Я изменил конструктор по умолчанию для моего класса, но кажется, что компилятор все еще вызывает конструктор по умолчанию - PullRequest
2 голосов
/ 05 мая 2019

Я создаю класс A, оператор перезаписи + и конструктор A(A&&), мне интересно, если я вызову

A a, b;
A c = a + b;

Мой конструктор A(A &&) называется?

Я попробовал некоторый код, но получаю очень запутанные результаты

//try2.cpp

#include <iostream>
#include <string>
using namespace std;
class A {
public:
  string s;
  A(A &&a) { s=std::move(a.s); cout<<"A(A &&a) called"<<endl;}
  A() {}
};

A operator+(const A &a, const A &b) {
  A c;
  c.s=a.s+b.s;
  return c;
}

int main() {
  A a,b;
  a.s = "123";
  b.s = "456";
  A c = a+b;
  cout<<c.s<<endl;
  return 0;
}

Я использовал gcc 7.0: g++ -std=c++1y try2.cpp

Вывод 123456, поэтому A(A &&a) не называется

Но тогда я меняю

A(A &&a) = delete;

Затем компилятор выдает ошибку:

try2.cpp: In function ‘A operator+(const A&, const A&)’:
try2.cpp:14:10: error: use of deleted function ‘A::A(A&&)’
   return c;
          ^
try2.cpp:7:3: note: declared here
   A(A &&a) = delete;
   ^
try2.cpp: In function ‘int main()’:
try2.cpp:21:11: error: use of deleted function ‘A::A(A&&)’
   A c = a+b;
           ^
try2.cpp:7:3: note: declared here
   A(A &&a) = delete;

Требуется конструктор A(A &&a). Но почему предыдущий код не вызывал его?

Ответы [ 2 ]

1 голос
/ 05 мая 2019

То, что здесь происходит, это copy elision . Ваш конструктор перемещения не вызывается, потому что у компилятора есть возможность создать ваш объект 'c', который используется внутри вашей функции operator +, прямо к объекту 'c' на сайте вызова. Это необязательная оптимизация, позволяющая избежать конструктора дополнительного перемещения (или копирования).

Вы сталкиваетесь с ошибкой компиляции при явном удалении конструктора перемещения, потому что это дополнительная оптимизация компилятором. Компилятору по-прежнему разрешается вызывать конструктор копирования / перемещения, если он этого хочет, но, явно удаляя конструктор перемещения, вы также неявно удаляете конструктор копирования. Это не оставляет опцию non-copy elision для компилятора, поэтому приводит к ошибке.

1 голос
/ 05 мая 2019

Именованная оптимизация возвращаемого значения .

Компилятор понял, что вместо создания A в области действия operator+ и перемещения его из operator+ в main, он может (в основном) просто сконструировать его в main и заставить operator+ работать со значением, которое находится в main.

Чтобы ваша программа была действительной, вам нужен какой-то конструктор, которыйпозволяет копировать значение, но компилятору не нужно его использовать, если он понимает, что может оптимизировать некоторые операции копирования / перемещения.

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