Я проверяю возможность копирования между тривиальными и нетривиальными типами, способными к копированию, когда возврат одной функции по значению напрямую передается по значению в другую функцию. Для нетривиального случая кажется, что объект передается напрямую, как и ожидалось, но для тривиального случая кажется, что выходной объект копируется в стек для создания объекта ввода для второй функции. У меня вопрос: почему?
Если это ожидается, это удивительно, поскольку нетривиально копируемый тип более эффективно передается между этими функциями.
Источник:
struct Trivial_Struct
{
unsigned char bytes[ 4 * sizeof( void* ) ];
};
struct Nontrivial_Struct
{
unsigned char bytes[ 4 * sizeof( void* ) ];
Nontrivial_Struct( Nontrivial_Struct const& );
};
Trivial_Struct trivial_struct_source();
Nontrivial_Struct nontrivial_struct_source();
void trivial_struct_sink( Trivial_Struct );
void nontrivial_struct_sink( Nontrivial_Struct );
void test_trivial_struct()
{
trivial_struct_sink( trivial_struct_source() );
}
void test_nontrivial_struct()
{
nontrivial_struct_sink( nontrivial_struct_source() );
}
G CC Выходная сборка:
test_trivial_struct():
sub rsp, 40
mov rdi, rsp
call trivial_struct_source()
push QWORD PTR [rsp+24]
push QWORD PTR [rsp+24]
push QWORD PTR [rsp+24]
push QWORD PTR [rsp+24]
call trivial_struct_sink(Trivial_Struct)
add rsp, 72
ret
test_nontrivial_struct():
sub rsp, 40
mov rdi, rsp
call nontrivial_struct_source()
mov rdi, rsp
call nontrivial_struct_sink(Nontrivial_Struct)
add rsp, 40
ret
godbolt.org . Я попробовал G CC, Clang и MSVC; Мне легче читать ассемблер G CC, но все компиляторы, похоже, делают подобный код для тривиально копируемого случая.
Mis c:
- Очевидно, что я могу случайно сделать Nontrivial_Struct тривиальным, если объявлю конструктор копирования внутри определения класса как
Nontrivial_Struct( Nontrivial_Struct const& ) = default
; если я добавлю Nontrivial_Struct::Nontrivial_Struct( Nontrivial_Struct const& ) = default;
после определения класса, тогда оно останется нетривиальным. - Я могу изменить «4» на большие значения, такие как «64», и это все еще происходит .
Предположение: