Копирование elision (NRVO) с удаленным копированием и перемещение конструкторов возможно? - PullRequest
0 голосов
/ 09 апреля 2020

В cppreference сказано, что

Конструкторы копирования / перемещения не обязательно должны присутствовать или быть доступными в операторе возврата, когда операнд является prvalue того же самого тип класса (игнорируя cv-qualification) в качестве возвращаемого функцией типа:

T f() {
    return T();
}

f(); // only one call to default constructor of T

Я правильно понимаю это право, и для того, чтобы приведенный выше пример работал, неизбежно иметь хотя бы одну копию или переместить конструктор?

Я попробовал следующее:

class Player
{
  //...
  public:
    Player();
    Player(std::string name);
    Player& operator=(const Player&) = delete;
    Player& operator=(Player&& p) = delete;
    Player(const Player& origin) = delete;
    Player(Player&& p) = delete;

    Player getEmptyPlayer() const {
      return Player("Name");
    }
}

//in main:

Player p1("It's Me");
Player p2 = p1.getEmptyPlayer();

Почему этот код компилируется и работает? Насколько я понимаю, метод getEmptyPlayer () должен вызывать конструктор копирования для копирования объекта при возврате. Из-за повышения эффективности компилятором, это не тот случай, но исключается копирование (NRVO), которое напрямую создает объект, где он должен быть, и не создает копию. Тем не менее, cppreference (см. Выше) говорит, что должен существовать доступный или существующий конструктор копирования / перемещения. Так что же здесь происходит?

Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 09 апреля 2020

Вопрос абсолютной чепухи. Цитата говорит: «Конструкторам копирования / перемещения нужно , а не присутствовать [...]».

Мне очень жаль, что я не читал правильно.

0 голосов
/ 09 апреля 2020

Разрешение копирования (NRVO) с удаленными конструкторами копирования и перемещения возможно?

Нет.

Если имеется копия (или перемещение), то тип должен быть копируемым (или подвижным). Тот факт, что копия (или перемещение) может быть оптимизирована, не делает такую ​​программу правильной.

Почему этот код компилируется и работает?

Поскольку существует копирование (и не перемещение) не требуется (начиная с C ++ 17).

Насколько я понимаю, на самом деле метод getEmptyPlayer () должен вызывать конструктор копирования для копирования объекта при возврате.

Это не начиная с C ++ 17.

Раньше это было необходимо до C ++ 17 (и вызов можно было исключить).

...