В этом ответе мы можем прочитать, что:
Я полагаю, есть небольшая разница между использованием
'\n'
или использованием"\n"
, но последний является массивом ( два) символа, который должен быть напечатан символ за символом, для которого должен быть установлен цикл, , который является более сложным, чем вывод одного символа .
выделенная шахта sup>
Это имеет смысл для меня. Я думаю, что для вывода const char*
требуется цикл, который будет проверять нулевой терминатор, который должен вводить больше операций, чем, скажем, простой putchar
(не подразумевающий, что std::cout
с char
делегатам называть это - это просто упрощение, чтобы представить пример).
Это убедило меня использовать
,
std::cout << '\n';
std::cout << ' ';
,
, а не
,
std::cout << "\n";
std::cout << " ";
,
. Здесь стоит упомянуть, что я знаю, что разница в производительности в значительной степени незначительна. Тем не менее, некоторые могут утверждать, что первый подход имеет намерение фактически передать один символ, а не строковый литерал, который, как оказалось, был длиной char
( две char
длиной, если считать '\0'
).
В последнее время я сделал небольшой пересмотр кода для кого-то, кто использовал последний подход. Я сделал небольшой комментарий по этому делу и пошел дальше. Затем разработчик поблагодарил меня и сказал, что он даже не думал о такой разнице (в основном, сосредоточившись на намерениях). Это не было никакого воздействия вообще (неудивительно), но изменение было принято.
Затем я начал задаваться вопросом , насколько точно это изменение значимо, поэтому я побежал к Годболту. К моему удивлению, он показал следующие результаты при тестировании на GCC (транк) с флагами -std=c++17 -O3
. Сгенерированная сборка для следующего кода:
#include
void str() {
std::cout << "\n";
}
void chr() {
std::cout << '\n';
}
int main() {
str();
chr();
}
удивила меня, поскольку кажется, что chr()
фактически генерирует ровно в два раза больше команд, чем str()
:
.LC0:
.string "\n"
str():
mov edx, 1
mov esi, OFFSET FLAT:.LC0
mov edi, OFFSET FLAT:_ZSt4cout
jmp std::basic_ostream >& std::__ostream_insert >(std::basic_ostream >&, char const*, long)
chr():
sub rsp, 24
mov edx, 1
mov edi, OFFSET FLAT:_ZSt4cout
lea rsi, [rsp+15]
mov BYTE PTR [rsp+15], 10
call std::basic_ostream >& std::__ostream_insert >(std::basic_ostream >&, char const*, long)
add rsp, 24
ret
Почему это? Почему оба они в конечном итоге вызывают одну и ту же функцию std::basic_ostream
с аргументом const char*
? Означает ли это, что буквальный подход char
не только не лучше , но на самом деле хуже , чем строковый литерал?