Рассмотрим следующий код:
#include <utility>
#include <string>
int bar() {
std::pair<int, std::string> p {
123, "Hey... no small-string optimization for me please!" };
return p.first;
}
(упрощено благодаря @ Jarod42 :-) ...)
Я ожидаю, что функция будет реализована как просто:
bar():
mov eax, 123
ret
но вместо этого реализация вызывает operator new()
, создает std::string
с моим литералом, затем вызывает operator delete()
. По крайней мере - это то, что делают g cc 9 и clang 9 ( GodBolt ). Вот вывод clang:
bar(): # @bar()
push rbx
sub rsp, 48
mov dword ptr [rsp + 8], 123
lea rax, [rsp + 32]
mov qword ptr [rsp + 16], rax
mov edi, 51
call operator new(unsigned long)
mov qword ptr [rsp + 16], rax
mov qword ptr [rsp + 32], 50
movups xmm0, xmmword ptr [rip + .L.str]
movups xmmword ptr [rax], xmm0
movups xmm0, xmmword ptr [rip + .L.str+16]
movups xmmword ptr [rax + 16], xmm0
movups xmm0, xmmword ptr [rip + .L.str+32]
movups xmmword ptr [rax + 32], xmm0
mov word ptr [rax + 48], 8549
mov qword ptr [rsp + 24], 50
mov byte ptr [rax + 50], 0
mov ebx, dword ptr [rsp + 8]
mov rdi, rax
call operator delete(void*)
mov eax, ebx
add rsp, 48
pop rbx
ret
.L.str:
.asciz "Hey... no small-string optimization for me please!"
Мой вопрос: ясно, что компилятор полностью осведомлен обо всем, что происходит внутри bar()
. Почему это не «исключение» / оптимизация строки прочь? Более конкретно:
- На базовом уровне c существует код между тогда
new()
и delete()
, что, как знает AFAICT компилятор, ничего не дает. - Во-вторых,
new()
и delete()
звонят сами. В конце концов, стандартная оптимизация небольших строк разрешена стандартным AFAIK, так что даже если clang / g cc не решил использовать это - он может иметь; это означает, что на самом деле нет необходимости вызывать new()
или delete()
там.
Меня особенно интересует, какая часть этого напрямую связана с языковым стандартом, а какая не является компилятором -optimality.