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