Почему инициализация строки из функции с помощью std :: string и std :: string & аналогична? - PullRequest
1 голос
/ 29 января 2020

Рассмотрим следующий код:

#include <string>
#include <sstream>

int main()
{
  const std::string name = "test test test";

  const std::string st = name.substr(0, 7);
  const std::string& st2 = name.substr(0, 7);
}

Я знаю о теоретической разнице, но при взгляде на код сборки вообще не видно разницы при -O2. См. Ниже:

st:

mov     ecx, 7
xor     edx, edx
lea     rdi, [rsp+32]
mov     rsi, rsp
call    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::substr(unsigned long, unsigned long) const

st2:

mov     ecx, 7
xor     edx, edx
lea     rdi, [rsp+64]
mov     rsi, rsp
call    std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::substr(unsigned long, unsigned long) const

1 Ответ

2 голосов
/ 30 января 2020

В случае инициализации st из-за copy elision возвращаемое значение name.substr напрямую встроено в строковый объект с именем st. В случае st2 возвращаемое значение напрямую создается в неназванном временном объекте, и st2 инициализируется ссылкой на этот неназванный объект.

В обоих случаях создается результат name.substr в объект автоматизации c длительность хранения, которая является локальной по отношению к основной без копирования или перемещения. Разница лишь в том, что у этого объекта есть имя в первом случае, а во втором - нет. У компилятора нет причин генерировать различный код для создания этих двух объектов.

(Привязка временного объекта к ссылке на const также продлевает время жизни временного объекта, предоставляя временному объекту то же время жизни, что и st. Это фактически дает временному имени имя st2, что делает его фактически идентичным объекту с именем st. Однако, поскольку это делается в последнем выражении функции, это не оказывает существенного влияния в вашем примере.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...