Почему «\ n» предпочтительнее «\ n» для выходных потоков?

В этом ответе мы можем прочитать, что:

Я полагаю, есть небольшая разница между использованием '\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 не только не лучше , но на самом деле хуже , чем строковый литерал?

28
задан Fureeish 28 July 2019 в 12:27
поделиться