2011-08-22 1 views
12

Я довольно новичок со строками C++, поэтому следующий шаблон может быть немного уродливым. Я просматриваю код, который я написал, прежде чем начинать интеграционное тестирование с помощью более крупной системы. Что я хотел бы знать, если это безопасно, или если он будет подвержен утечке памяти?Возвращает объект std :: string 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, но я стараюсь быть немного более ясным в своем коде (и меньше полагаюсь на стиль функции побочных эффектов).

+0

В первой функции вы, вероятно, могли бы просто «вернуть строку» («Строка»); и имеют тот же результат. – luiscubal

+0

@luiscubal Это упрощенный пример, иллюстрирующий проблему. – Stephen

+2

@luiscubal even 'return" Строка ";' отлично, поскольку std :: string являются конструктивными с c строками. – log0

ответ

10

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

string myString = somefunc(); 

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

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

2

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

7

Да, делая

return returnString 

Вы призываете струны copy constructor. Который выполняет копирование * из returnString во временную (ака RValue), который занимает место «SomeFunc()» в вызывающем выражении:

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

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

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

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

+1

Фактически, выполняется ли глубокая копия или нет, полностью зависит от конкретной реализации стандартной библиотеки, которую вы используете. GCC использует COW, поэтому конструктор копирования просто предполагает увеличение счетчика. –

+0

@Matthieu хороший момент Я уточнил свой ответ. Благодарю. –

5

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

0

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

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

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

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

Это обходит оптимизацию возвращаемого значения, обычно выполняемую компиляторами, поэтому это не улучшение. –

+0

@Bo Persson Я никогда не говорил о повышении производительности. – log0

+0

'Что ты хочешь, чтобы ... почему ты так говоришь? Я вижу мало преимуществ для вашего кода над тем, что он делает. –