Подтвердить что ты не робот

Почему в этом случае вызывается конструктор ссылок r-value?

#include<iostream>
using namespace std;

struct B{};

struct A
{
    A(const B &)
    {
        cout<<"A(const B &)"<<endl;
    }
    A(B &&)
    {
        cout<<"A(B &&)"<<endl;
    }
};

A get()
{
    B b;
    return b;
}

int main()
{
    get();
}

Я тестировал код с VС++ 14.2 и GCC 5.4.0, оба из них выводят:

A(B &&)

Почему вывод не

A(const B &)

?

Имеет ли этот код какое-либо отношение к copy elision? (Но A и B - разные типы, поэтому copy elision здесь не должно работать)

4b9b3361

Ответ 1

Правила return-as-rvalue изменились в ответ на обзор перед публикацией С++ 14. Это изменение было добавлено в конце процесса и зафиксировано CWG Issue 1579, которое вносит изменения в 12.8/32 с формулировкой:

или когда выражение в выражении return является (возможно, в скобках) id-выражением, которое называет объект с автоматическим временем хранения, объявленным в теле

Это означает, что возврат любой локальной переменной теперь рассматривает объект, назначенный этой переменной, как если бы это было сначала rvalue (повторное попытку, если сбой при перегрузке завершен).

Поскольку проблема CWG была принята как дефект в языке, компиляторы могут реализовать это новое правило даже в режиме "С++ 11". Точка дефекта заключается в том, что "это всегда предназначалось для работы таким образом", поэтому это не является строго выражением изменений между С++ 11 и С++ 14, а, скорее, значение С++ 11 было изменено в 2014 году.

Ответ 2

Копирование elision связано с A, не созданным в стеке get(). Случается, что возвращенный b (временный, так как "будет умирать из-за возврата": это с тех пор, как С++ 14), используется для создания скопированного текста A в основном стеке-фрейме.

И поскольку временные объекты связывают ссылки r-value с тем, что вы наблюдали.