Безопасен ли возврат объекта C ++ std :: string от утечек памяти? - PullRequest
12 голосов
/ 22 августа 2011

Я довольно новичок со строками C ++, поэтому следующий шаблон может быть немного беспорядочным. Я рассматриваю некоторый код, который написал перед началом интеграционного тестирования с более крупной системой. То, что я хотел бы знать, является ли это безопасным, или если это будет склонно к потере памяти?

string somefunc( void ) {
    string returnString;
    returnString.assign( "A string" );
    return returnString;
}

void anotherfunc( void ) {
    string myString;
    myString.assign( somefunc() );
    // ...
    return;
}

Насколько я понимаю, значение returnString присваивается новому объекту myString, а затем объект returnString уничтожается как часть разрешения вызова somefunc. В какой-то момент в будущем, когда myString выйдет из области видимости, он тоже будет уничтожен.

Я бы обычно передавал указатель на myString в somefunc () и непосредственно назначал значения myString, но я стараюсь быть немного более понятным в своем коде (и меньше полагаться на стиль функции побочного эффекта).

Ответы [ 5 ]

10 голосов
/ 22 августа 2011

Да, возвращать string таким способом (по значению) безопасно, хотя я бы предпочел назначить его следующим образом:

string myString = somefunc();

Это легче читать, а также более эффективно (сохранениесоздание пустой строки, которая затем будет перезаписана при следующем вызове assign).

std::string управляет собственной памятью, и в ней правильно записан конструктор копирования и оператор присваивания, поэтомубезопасно использовать строки таким образом.

7 голосов
/ 22 августа 2011

Да, делая

   return returnString

Вы вызываете конструктор копирования строки . Который выполняет копию * returnString во временную (aka rValue), которая заменяет "somefunc ()" в вызывающем выражении:

   myString.assign( somefunc() /*somefunc()'s return becomes temporary*/);

Это, в свою очередь, передается для присваивания и используется по назначению для выполнения копирования в myString.

Так что в вашем случае конструктор копирования строки гарантирует глубокое копирование и не допускает утечек памяти.

* Обратите внимание, что это может быть или не быть истинной глубокой копией, поведение конструктора копирования зависит от конкретной реализации. Некоторые строковые библиотеки реализуют функцию копирования при записи, в которой есть некоторая внутренняя бухгалтерия, предотвращающая копирование до тех пор, пока она действительно не понадобится.

5 голосов
/ 22 августа 2011

Вы в полной безопасности, потому что вы возвращаете строку по значению, где строка будет «скопирована», а не по ссылке. Если бы вы вернули std::string &, то вы сделали бы это неправильно, так как у вас была бы свисающая ссылка. Даже некоторые компиляторы могут выполнить оптимизацию возвращаемого значения , которая даже не скопирует строку по возвращении. См. этот пост для получения дополнительной информации.

2 голосов
/ 22 августа 2011

Да, это (по крайней мере, нормально) безопасно.Одним из самых основных вкладов практически любого разумного строкового класса является способность действовать как базовое значение, для которого обычное присваивание, возврат и т. Д. «Просто работают».

0 голосов
/ 22 августа 2011

Как вы сказали, строка returnString создается внутри somefunc, и копия возвращается, когда функция возвращается.Это совершенно безопасно.

Вам нужно дать ссылку на myString на somefunc (не используйте указатель).Будет совершенно ясно:

void somefunc( string& myString ) {
  myString.assign( "A string" );
}

void anotherfunc( void ) {
  string myString;
  somefunc(myString);
  // ...
  return;
}
...