Сравнение кода: какой код лучше использовать с точки зрения эффективности? - PullRequest
0 голосов
/ 23 апреля 2019

Какой код лучше использовать: для инициализации строки?

bool flag = /*function call...*/
string str = "abc";
if(flag)
  str = "bcd";

Или

string str;
if(flag)
  str = "bcd";
else
  str = "abc";

Или

string str("abc");
if(flag) 
  str = "bcd";

Заранее спасибо.

Ответы [ 2 ]

10 голосов
/ 23 апреля 2019

Это микрооптимизация, которую вы не должны делать.Программа на C ++ - это , а не описание сборки в удобочитаемом формате.Это высокоуровневое описание поведения вашей программы.Работа компилятора заключается в создании ассемблера, который демонстрирует указанное нами поведение.

Вы не указали, как используете результирующую строку, но если я сделаю несколько предположений и переверну ваш кодв маленькие функции ...

#include <string>

std::string foo1(bool flag) {
    std::string str = "abc";
    if(flag)
        str = "bcd";
    return str;
}

std::string foo2(bool flag) {
    std::string  str;
    if(flag)
        str = "bcd";
    else
        str = "abc";
    return str;
}

std::string foo3(bool flag) {
    std::string str("abc");
    if(flag) 
        str = "bcd";
    return str;
}

.. Clang 8.0 произведет в значительной степени эквивалентную сборку для трех случаев (и особенно для foo1 и foo3) 1 .Вы можете увидеть это на Godbolt .

Что неудивительно, поскольку наблюдаемое поведение, предписанное вашими тремя фрагментами, равно того же и не зависит от выбранного фрагмента.,Так что не зацикливайтесь на микрооптимизации.Остановимся на описании оптимального поведения в более широком масштабе.


1 - Ну, - это заметная ветвь в foo2, нокод, который будет выполняться во время выполнения, всегда будет представлять собой одно потенциальное выделение и копию содержимого строки.Здесь может быть некоторая стоимость ошибочного прогнозирования веток, но если только она не находится в действительно узком цикле, я не считаю, что это стоит рассмотреть.Более того, использование std::string в таком цикле само по себе может считаться сомнительным.

2 голосов
/ 23 апреля 2019

C ++ использует инициализацию:

bool flag = foo();
string str { flag ? "bcd" : "abc" };

flag определяет, какой строковый литерал используется при вызове std::string::string(const char*).Но есть один вызов, строится один строковый объект, и нет присваивания.

[edit] Перевернули строковые литералы.В C ++, как для конструкции if, так и для конструкции ?:, «истинный» случай стоит первым, а затем «ложный» случай последним.Но вопрос перевернул их, «abc» был первым для дела flag==false.

...