Подтвердить что ты не робот

Является ли объект С++ std::string безопасным для утечки памяти?

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

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, но я стараюсь быть немного более ясным в своем коде (и меньше полагаюсь на стиль функции побочных эффектов).

4b9b3361

Ответ 1

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

string myString = somefunc();

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

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

Ответ 2

Да, делая

   return returnString

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

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

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

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

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

Ответ 3

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

Ответ 4

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

Ответ 5

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

Вы хотите дать ссылку на myString на somefunc (не использовать указатель). Это будет совершенно ясно:

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

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