LINUX.ORG.RU

Удаленный move конструктор и передача по значению временного объекта

 ,


0

2

Добрый день,

имеется такой сферический в вакууме код

#include <iostream>


class A
{
        int i;
public:
        A() {std::cout << "A" << std::endl;}
        A(const A&) {std::cout << "const A&" << std::endl;}
//      A(A&&) {std::cout << "A&&" << std::endl;}
        A(A&&) = delete;
        ~A() {std::cout << "~A" << std::endl;}
};

void f(A a)
{
}
int main()
{
        f(A());

        return 0;
}

В g++ 6.3 (с -std=c++17) это не компилируется с ошибкой error:

use of deleted function ‘A::A(A&&)’

В g++ 7.2 (с -std=c++17) это собирается.

Вопрос: появилось ли в конечном варианте стандарта какое-нибудь требование относительно этого поведения? Если нет, то чем объяснить такое поведение компиляторов.

★★★★★

С C++17 в крестах гарантированный copy elision для вышеприведённого случая. В g++ 6.3 видать просто не заимплеменчен он.

zamazan4ik ★★
()
Ответ на: комментарий от UVV

Если нет, то предположу, что Copy elision сработало.

Вопрос же не в этом. Почему в gcc 6.3 не компилится. То что там copy elision оно и ежу понятно. Или имеется в виду, что правила copy elision в с++14 (и возможно ранних черновиках c++17) были не столь однозначными? Тогда ок, понятно.

Dudraug ★★★★★
() автор топика
Ответ на: комментарий от zamazan4ik

Хм, ну я так и подумал. Хотел убедиться. Вопрос закрыт.

Dudraug ★★★★★
() автор топика

use of deleted function ‘A::A(A&&)’

А где в приведенном коде вызов этого конструктора?

Как мне кажется в строке

f(A());

Будет сперва вызван A::A(), а потом A::A(const &A), или нет?

s3rjke
()
Ответ на: комментарий от Dudraug

Ну если A(A&&) не удален, то должен был быть вызван именно он, в случае без copy elision.

Можете объяснить, почему? Разве вот это f(A()); не эквивалентно

A some_var;
f(some_var); // тут вызывается конструктор копии A(const A&) для передачи some_var в функцию по значению
?

s3rjke
()
Ответ на: комментарий от s3rjke

Нет, f(A()) не эквивалентен твоему коду. A() тут - неименованный объект, это rvalue. А значит должен сработать конструктор перемещения, после дефолтного. Но на деле по с++17 должен сработать только дефолтный.

Dudraug ★★★★★
() автор топика
Ответ на: комментарий от Dudraug

Нет, f(A()) не эквивалентен твоему коду. A() тут - неименованный объект, это rvalue. А значит должен сработать конструктор перемещения, после дефолтного.

Ужас какой, почему так сложно. =\ Придется разбираться.

s3rjke
()

Удаление move-конструктора не исключает его из рассмотрения при overload resolution и move-конструктор выбирается для вызова. Это до C++17. В C++17+ никакого, даже концептуально, вызова move-конструктора здесь не должно быть поэтому на его состояние пофиг.

utf8nowhere ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.