2014-10-27 2 views
9

У меня есть 2 способа вернуть пустую строку из функции.Возвращение пустой строки: эффективный способ в C++

1)

std::string get_string() 
{ 
    return ""; 
} 

2)

std::string get_string() 
{ 
    return std::string(); 
} 

которых один является более эффективным и почему?

+12

Ни то, ни другое. Используйте 'return {};'. –

+2

И как это относится к C? – crashmstr

+3

Это попадает в сферу бесполезной микро-оптимизации, которую ваш компилятор будет оптимизировать, используя RVO и копию elision. – CoryKramer

ответ

19

Сделал некоторые копания. Ниже приведен пример программы и соответствующая сборка:

Код:

#include <string> 

std::string get_string1(){ return ""; } 

std::string get_string2(){ return std::string(); } 

std::string get_string3(){ return {}; }   //thanks Kerrek SB 

int main() 
{ 
    get_string1(); 
    get_string2(); 
    get_string3(); 
} 

Монтаж:

__Z11get_string1v: 
LFB737: 
    .cfi_startproc 
    pushl %ebx 
    .cfi_def_cfa_offset 8 
    .cfi_offset 3, -8 
    subl $40, %esp 
    .cfi_def_cfa_offset 48 
    movl 48(%esp), %ebx 
    leal 31(%esp), %eax 
    movl %eax, 8(%esp) 
    movl $LC0, 4(%esp) 
    movl %ebx, (%esp) 
    call __ZNSsC1EPKcRKSaIcE 
    addl $40, %esp 
    .cfi_def_cfa_offset 8 
    movl %ebx, %eax 
    popl %ebx 
    .cfi_restore 3 
    .cfi_def_cfa_offset 4 
    ret $4 
    .cfi_endproc 

__Z11get_string2v: 
LFB738: 
    .cfi_startproc 
    movl 4(%esp), %eax 
    movl $__ZNSs4_Rep20_S_empty_rep_storageE+12, (%eax) 
    ret $4 
    .cfi_endproc 

__Z11get_string3v: 
LFB739: 
    .cfi_startproc 
    movl 4(%esp), %eax 
    movl $__ZNSs4_Rep20_S_empty_rep_storageE+12, (%eax) 
    ret $4 
    .cfi_endproc 

Это был скомпилирован с -std=c++11 -O2.

Вы можете видеть, что для оператора return ""; существует довольно много работы и сравнительно мало для return std::string и return {}; (эти два идентичны).

Как сказал Фрерих Раабе при передаче пустого C_string, ему все же необходимо обработать его, а не просто выделить память. Кажется, что это не может быть оптимизировано далеко (по крайней мере, не НКУ)

Так что ответ определенно использовать:

return std::string(); 

или

return {}; //(c++11) 

Хотя, если вы не возвращаются много пустых строк в критическом кривом производительности (ведение журнала, я думаю?), разница будет по-прежнему незначительной.

+0

Возможно, для этого требуется обновление по состоянию на 2017 год, все три возможности возвращают, дают тот же результат asm, поэтому нет никаких проблем с возвратом «" или std :: string {} или {}. Протестировано в компиляторе для clang & gcc –

+0

@TomazCanabrava Я должен был указать версию gcc в то время ... Если вы хотите предоставить версии clang и gcc, которые вы протестировали, я отмечу это в ответе. – Baldrickk

+0

@TomazCanabrava на самом деле, когда я пытаюсь gcc и clang с выше, я получаю аналогичные результаты (gcc 7.1/clang4.0.0). Интересно, что Visual Studio (2015) предоставляет результаты, которые согласуются между каждой версией, но во многих случаях работает больше. – Baldrickk

3

Последняя версия никогда не медленнее, чем первая. Первая версия вызывает конструктор std::string, взяв строку C, которая затем должна сначала вычислить длину строки. Несмотря на то, что это быстро сделать для пустой строки, это, конечно, не быстрее, чем вообще не делать.

+0

Как это константа, которая возвращается, является ли вычисление длины не оптимизированным компилятором? Если нет, не так ли? – Baldrickk

+0

@Baldrickk Он вызывает один конструктор аргументов 'std :: string'.Я не думаю, что есть много (если есть) компиляторов, которые достаточно умны, чтобы вывести, что один конструктор аргументов является эквивалентом конструктора, берущего как указатель, так и размер при условии, что он проходит на один меньше, чем размер строки literal (имеет конечный '' \ 0''). –

+0

@JamesKanze: некоторые компиляторы оптимизируют 'strlen()' в строковом литерале - я попросил, чтобы функция была добавлена ​​на SparcWorks C++ более десяти лет назад - не знаю, когда-либо делали это - GCC уже это сделал. Тем не менее - я бы не ожидал, что реализация C++ будет использовать 'strlen' ... никогда не знаю. –

Смежные вопросы