#c #string #pointers
#c #строка #указатели
Вопрос:
я не знаю, но у меня это не работает, я получаю значение garbege при попытке установить значение char * из функции, которая возвращает строку std :
string foo()
{
string tmp ="dummy value";
return tmp;
}
char* cc = (char *) foo().c_str(); // if i remove the casting im getting error
// when i print the cc i get garbage
printf("%s",cc);
Ответ №1:
Время жизни данных, на которые указывает cc
, совпадает с временем жизни строки, из которой они были получены (в лучшем случае — если вы измените строку, она станет еще короче).
В вашем случае возвращаемое значение foo()
является временным, которое уничтожается в конце инициализации cc
.
Чтобы избежать ошибки компиляции в, char *cc = foo().c_str()
вам не следует приводить к char*
, вам следует переключиться на const char *cc
, поскольку const char*
это то, что c_str()
возвращает. Однако это все еще не решает основную проблему.
Простейшими исправлениями являются:
printf("%s", foo().c_str()); // if you don't need the value again later
const string s = foo();
const char *cc = s.c_str(); // if you really want the pointer - since it's
// in the same scope as s, and s is const,
// the data lives as long as cc's in scope.
string s = foo();
printf("%s", s.c_str()); // if you don't store the pointer,
// you don't have to worry about it.
std::cout << foo(); // printf isn't bringing much to this party anyway.
Ответ №2:
Результатом foo
является временный объект, который уничтожается к концу char * cc = ...
строки. Сохраните его в постоянной ссылке:
const stringamp; cc = foo();
printf ("%s", cc.c_str());
Комментарии:
1. Совершенно верно;
const reference
продление срока службы rvalue оказывается экзотическим правилом, и «просто» запоминание значения также подошло бы. (Вероятно, оптимизировано с использованием семантики перемещения в C 11).2. При условии, что семантика перемещения или RVO находятся в разработке, использование типа значения в значительной степени эквивалентно. Но ссылка не позволяет нам полагаться на оптимизацию компилятора.
3. @xtofl: при условии, что значение сохраняется с использованием
foo()
в качестве инициализатора, нет необходимости в семантике перемещения. Скучный старый C 03 copy elision сделает это.4. 1 за объяснение того, что не так с кодом и предоставление решения проблемы «в лучшем мире» 🙂
Ответ №3:
Передайте ячейку памяти foo () и попросите foo изменить это:
void foo (string* _out_newStr)
{
_out_newStr->assign("dummy string"); //This is wrong -> _out_newStr = "dummy string";
return;
}
Затем, когда вы используете функцию «c_str()» объекта string, вы будете возвращать постоянное значение char *, как уже указывалось.
Комментарии:
1. @Nawaz Это полезно … хотите расширить? Я тоже готов учиться.
2. @Dennis:
_out_newStr
это указатель наstd::string
, как вы можете присвоить ему символьный литерал? Ваш код даже не будет компилироваться.3. И даже если вы измените его на
*_out_damned_spot = "dummy string"
, использование отдельного параметра out в C является попыткой оптимизации, которая обычно не требуется. Это вполне может быть медленнее , чем полагаться на RVO, поскольку вызывающий объект должен создать пустую строку, а затем вы присваиваете ей значение, тогда как при достаточном удалении копирования строка вызывающего объекта может быть сконструирована непосредственно из литерала. Просто возвращайте по значению, пока не доказано обратное.4. @Nawaz: Ты прав. Этого не произошло. Приношу извинения оператору. На самом деле я не работал со строками около 3 лет из-за возраста того, над чем я работаю. Я изменил свой пост.
5. @Dennis: Отменил понижающий голос и теперь проголосовал за него с повышением. Кстати, вы могли бы также использовать ссылку :
void foo(string amp; s) { s = "dummy string"; }
. Теперь все в порядке.
Ответ №4:
Фрагмент кода вызывает неопределенное поведение, потому что временное, std::string
созданное в результате вызова, уничтожается в конце выражения, но cc
которое указывает на уничтоженный объект, все еще используется даже после этого.
Ответ №5:
Как насчет:
printf("%s", foo.c_str() );
Или, что еще лучше, забудьте об использовании символьных указателей.
Комментарии:
1. Как насчет
std::cout << foo()
. 😀