Я играл с различными методами инициализации и оценивал опыт разработчика, который они предоставляют для различных вариантов использования и их влияния на производительность. В процессе я написал два фрагмента кода, один с прямой инициализацией и один со списком инициализаторов.
Direct:
class C {
public:
char* x;
C() : x(new char[10] {'0','1'}) {}
};
C c;
Список инициализаторов:
#include <utility>
#include <algorithm>
class C {
public:
char* x;
C(std::initializer_list<char> il) {
x = new char[10];
std::copy(il.begin(), il.end(), x);
}
};
C c = {'0','1'};
Я ожидал, что std::initializer_list
создаст ту же сборку, и хотя я могу понять, почему она может быть хуже (выглядит более сложной), я бы задал здесь совсем другой вопрос, если бы это было на самом деле хуже. Вообразите мое удивление, когда я увидел, что он генерирует лучше код с меньшим количеством инструкций!
Ссылка на Godbolt с помощью приведенных выше фрагментов - https://godbolt.org/z/i3XZ_K
Direct:
_GLOBAL__sub_I_c:
sub rsp, 8
mov edi, 10
call operator new[](unsigned long)
mov edx, 12592
mov WORD PTR [rax], dx
mov QWORD PTR [rax+2], 0
mov QWORD PTR c[rip], rax
add rsp, 8
ret
c:
.zero 8
Список инициализаторов:
_GLOBAL__sub_I_c:
sub rsp, 8
mov edi, 10
call operator new[](unsigned long)
mov edx, 12592
mov QWORD PTR c[rip], rax
mov WORD PTR [rax], dx
add rsp, 8
ret
c:
.zero 8
Сборка почти такая же, за исключением дополнительной инструкции mov QWORD PTR [rax+2], 0
, которая на первый взгляд выглядит как завершение массива char с помощью нулевой символ. Однако в IIR C только строковые литералы (например, "01"
) автоматически завершаются нулевым символом, а не литералами массива символов.
Буду признателен за понимание того, почему сгенерированный код отличается, и что я могу сделать ( если возможно), чтобы сделать прямой случай лучше.
Кроме того, я нуб, когда дело доходит до сборки x86, поэтому дайте мне знать, если я упускаю что-то очевидное.
РЕДАКТИРОВАТЬ: Это только получает хуже, если я добавлю больше символов - https://godbolt.org/z/e8Gys_