Это хорошая идея, чтобы вернуть "const char *" из функции? - PullRequest
24 голосов
/ 25 марта 2010

Теперь у меня есть функция, которая должна возвращать строку. Я видел конкретную реализацию, где он возвращает const char * из функции.

Примерно так:

const char * GetSomeString() 
{ 
  ........   
  return somestlstring.c_str(); 
}

SomeOtherFoo ()
{
  const char * tmp = GetSomeString();
  string s = tmp;
}

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

Пожалуйста, дайте мне ваши предложения. У меня есть чувство возврата const char *, это может привести к хаосу ..

Спасибо, Арджун

Ответы [ 6 ]

27 голосов
/ 25 марта 2010

В зависимости от того, что somestlstring и что там делается.

Если это локальная переменная, вы возвращаете указатель в память, которая освобождается после завершения GetSomeString, так что это висячий указатель и ошибка.

Все сводится к времени жизни somestlstring и операциям, которые вы над ним выполняете. Указатель, возвращаемый .c_str(), гарантированно действителен только до следующей операции мутирования в строке. Так что если что-то изменится somestlstring от вызова на .c_str() и до того, как s будет построено, вы окажетесь в неопределенной зоне поведения.

6 голосов
/ 25 марта 2010

Если вы спрашиваете о времени жизни const char *, возвращаемом функцией std::string c_str(), она действительна до тех пор, пока вы не измените строку, из которой вы ее получили, или пока строка не будет уничтожена. Вернуть его из функции - это нормально (хотя я бы сказал, что это не очень хорошая практика), если вы помните эти два факта.

3 голосов
/ 25 марта 2010

Это нормально при условиях, разработанных @Neil. Однако лучшим способом было бы вернуть ссылку на строку

string const& GetSomeString() 
{ 
  ........   
  return somestlstring; 
}

string s = GetSomeString();

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

string GetSomeString() 
{ 
  ........   
  return somestlstring; // can be a local automatic variable
}

string s = GetSomeString();
2 голосов
/ 25 марта 2010

Это не здорово - как долго память вашей строки держится? Кто несет ответственность за его удаление? Нужно ли вообще его удалять?

Вам лучше возвращать строковый объект, который отвечает за выделение и освобождение строковой памяти - это может быть std :: string или QString (если вы используете Qt), или CString (если вы ' использовать MFC / ATL).

на немного другой ноте, будет ли когда-нибудь ваша строка в юникоде? Большинство строковых классов могут прозрачно работать с данными Юникода, но const char не будет ...

1 голос
/ 25 марта 2010

Чтобы добавить несколько сценариев, в которых это будет нормально:

  • somestlstring - глобальная переменная, инициализированная в той же единице перевода (.cpp), что и GetSomeString ()
  • somestlstring является нестатическим членом класса, а GetSomeString является членом этого класса. В этом случае время жизни возвращаемого указателя должно быть задокументировано (в основном - как говорили другие - до тех пор, пока не изменится стринг или не будет уничтожен объект)
  • вы возвращаете char const * в строку, инициализированную буквально или во время компиляции
1 голос
/ 25 марта 2010

Зависит от того, где находится переменная somestlstring.

Если это переменная локаль для функции GetSomeString(), то это явно неправильно. Действительно, переменная somestlstring уничтожается в конце функции, и, таким образом, const char * указывает на то, что больше не существует.

Если это глобальная переменная, то этот код верен.

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