как установить значение char * из строки std (c_str()) не работает

#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() . 😀