Как вернуть string из функции c
Вот так работает:
#include using namespace std; char* Fun(); const int BSIZE = 20; int main() < char* stst = new char[BSIZE]; stst = Fun(); cout char* Fun()
Но выдаётся предупреждение:
| warning C4172: возвращение адреса локальной или временной переменной |
Последний раз редактировалось 8Observer8; 26.05.2012 в 15:22 .
| 8Observer8 |
| Посмотреть профиль |
| Найти ещё сообщения от 8Observer8 |
Пользователь
Регистрация: 29.04.2012
Сообщений: 36
Сообщение от 8Observer8
Вот так работает:
#include using namespace std; char* Fun(); const int BSIZE = 20; int main() < char* stst = new char[BSIZE]; stst = Fun(); cout char* Fun()
эм, изменил у себя, всё равно выдаёт символы + ошибку
использую Microsoft Visual Studio Developer 2011
Сообщение от _Bers
возвращаешь наружу мертвый элемент.
const char* Fun()
нужно возвращать в принципе любую строку, так не вариант
Последний раз редактировалось Stilet; 27.05.2012 в 10:32 .
Регистрация: 16.12.2011
Сообщений: 2,329
Сообщение от Kaela
нужно возвращать в принципе любую строку, так не вариант
Не вариант - возвращать наружу указатель/ссылку на дохлый объект.
Если нужно возвращать в принципе любую строку, стало быть нужен код, который эти строки создает.
Покажи, как ты будешь создавать в принципе разные строки
[QUOTE=8Observer8;1050825]Вот так работает:
Не работает так. То, что память ещё остаётся непопорченной - не значит, что она живая. Твой указатель смотрит на убитый объект.
Последний раз редактировалось Stilet; 27.05.2012 в 10:33 .
Пользователь
Регистрация: 29.04.2012
Сообщений: 36
Сообщение от _Bers
Не вариант - возвращать наружу указатель/ссылку на дохлый объект.
Если нужно возвращать в принципе любую строку, стало быть нужен код, который эти строки создает.
Покажи, как ты будешь создавать в принципе разные строки
я пишу обратную польскую запись
суть в том, что я в одной функции преобразовываю строку
и хочу её передать аргументом в другую функцию
там я её заполняю посимвольно
можно реализовать через cin.getline()
но почему дохлый объект?
указатели ведь указывают на адрес даже, когда из функции выходим
Регистрация: 16.12.2011
Сообщений: 2,329
[QUOTE=8Observer8;1050825]Вот так работает:
Не работает так. То, что память ещё остаётся непопорченной - не значит, что она живая. Твой указатель смотрит на убитый объект.
Если совсем точно - литерная константа, определяемая внутри функции по стандарту имеет класс памяти static
Поэтому, вот такой код валидный:
const char* Fun()
Стандарт гарантирует, что адрес, который вернётся из такой функции, будет указывать на const char* const = "privet"
Цена за это: не возможность освободить память занимаемую строкой "privet" до конца жизни приложения.
Тот факт, что вы присваеваете результат (const char* const) простому char* - раздолбайство языка си.
Так делать некорректно, но язык позволяет (типа все знают, что это фейл, но всем пофигу, да).
Пользователь
Регистрация: 29.04.2012
Сообщений: 36
[QUOTE=_Bers;1050855]
Сообщение от 8Observer8
Вот так работает:
Не работает так. То, что память ещё остаётся непопорченной - не значит, что она живая. Твой указатель смотрит на убитый объект.
Если совсем точно - литерная константа, определяемая внутри функции по стандарту имеет класс памяти static
Поэтому, вот такой код валидный:
const char* Fun()
Стандарт гарантирует, что адрес, который вернётся из такой функции, будет указывать на const char* const = "privet"
Цена за это: не возможность освободить память занимаемую строкой "privet" до конца жизни приложения.
Тот факт, что вы присваеваете результат (const char* const) простому char* - раздолбайство языка си.
Так делать некорректно, но язык позволяет (типа все знают, что это фейл, но всем пофигу, да).
тогда как мне реализовать возврат строки из функции?
если я не знаю, какая она будет, а хочу возвращать рандомную?
Как вернуть массив строк C++?
Учи матчасть: массив из функции вернуть нельзя. Можно вернуть указатель на массив или структуру содержащую массив.
string arr[0] = func(exp);
Слева в этом выражении стоит массив из нуля элементов. Справа -- указатель на string.
Что ты хотел этим выражением сказать?
Ответ написан более трёх лет назад
Комментировать
Нравится Комментировать
Программист на «си с крестами» и не только
ВНИМАНИЕ: У вас есть пара тонких мест.
РАЗ. не забудьте, что строковые литералы в Си — это нуль-терминированные строки, и "\0" по факту будет пустой строкой. Строку из одного нулевого символа можно загнать в string — например, конструктором string(begin, end) или s += '\0', но не конструктором string(const char*).
ДВА. Этот static будет инициализирован при первом вызове. Второй вызов вернёт тот же массив.
ТРИ. Строчку лучше передавать как string *func(const string& s) <>
К делу. Массив — это довольно сложный объект, и возникает вопрос: кто этим массивом будет владеть после того, как он покинет пределы функции?
1. Владеет система времени выполнения. Это отлично ответил Роман, дам только ключевую строчку.
string* arr = func(exp);
НЕЛЬЗЯ ИСПОЛЬЗОВАТЬ: если массив используется в чьих-то «конских» конструкторах-деструкторах статических объектов (из-за отсутствия модулей Си++ не позволяет установить на уровне языка порядок создания/уничтожения статических объектов).
2. Владеет какой-то объект.
string *func(string s)
НЕЛЬЗЯ ИСПОЛЬЗОВАТЬ: ну, это уж разбирайтесь сами с этим объектом, сколько он будет жить и насколько долго он будет держать массив. В данном случае каждый новый вызов уничтожает старый массив. (Код корявый, потому что последний массив не уничтожается.)
3. Владеет тот, кто вызывает. Лучше для таких целей использовать какой-нибудь std::vector.
vector func(string s) < vectorr; r.reserve(3); r.push_back("qwe"); r.push_back(s); r.push_back(std::string()); return r; >
Как вернуть string из функции c
Здравствуйте, Аноним, Вы писали:
А>Всех с наступяющими праздниками.
А>Господа, есть следующая функция:
А>
А>////////////////////////////////////////////////////////////////////////// А>const std::string &CXxxDlg::GetMyStr() А> < А>static std::string stVar = "bla-bla-bla"; А>. А>. А> return stVar; А>> А>. А>std::string st = GetMyStr(); А>. А>
А>Вопрос: Корректно ли возвращать так std::string? Сколько будет "жить" эта stVar.
Я бы не стал так возвращать string и вообще любой другой объект. В момент вызова оператора= тот объект ссылку на которого мы вернули уже разрушен.
Если хочешь возвращать по ссылке, лучше это делать через параметры.
CXxxDlg::GetMyStr(string& o_str)
Re[2]: Возврат std::string из функции
| От: | TarasKo |
| Дата: | 29.12.06 09:55 |
| Оценка: |
TK>Я бы не стал так возвращать string и вообще любой другой объект. В момент вызова оператора= тот объект ссылку на которого мы вернули уже разрушен если конечно он был создан в стеке.
TK>Если хочешь возвращать по ссылке, лучше это делать через параметры.
Re[2]: Возврат std::string из функции
| От: | Аноним | |
| Дата: | 29.12.06 09:56 | |
| Оценка: | -1 | |
Нифиганиразрушен. Там static. Все работает. Остальное — дело вкуса.
Re: Возврат std::string из функции
| От: | Аноним |
| Дата: | 29.12.06 10:11 |
| Оценка: |
Здравствуйте, Аноним, Вы писали:
А>
А>////////////////////////////////////////////////////////////////////////// А>std::string CXxxDlg::GetMyStr() А> < А>std::string stVar = "bla-bla-bla"; А>
А>Вопрос: Корректно ли возвращать так std::string? Сколько будет "жить" эта stVar.
Так почему сделать не хочешь?
Re[3]: Возврат std::string из функции
| От: | TarasKo |
| Дата: | 29.12.06 10:16 |
| Оценка: |
Здравствуйте, Аноним, Вы писали:
А>Нифиганиразрушен. Там static. Все работает. Остальное — дело вкуса.
А блин static не заметил. Сорри
Re: Возврат std::string из функции
| От: | remark | http://www.1024cores.net/ |
| Дата: | 29.12.06 10:23 | |
| Оценка: |
Здравствуйте, Аноним, Вы писали:
А>Всех с наступяющими праздниками.
А>Господа, есть следующая функция:
А>
А>////////////////////////////////////////////////////////////////////////// А>const std::string &CXxxDlg::GetMyStr() А> < А>static std::string stVar = "bla-bla-bla"; А>. А>. А> return stVar; А>> А>. А>std::string st = GetMyStr(); А>. А>
А>Вопрос: Корректно ли возвращать так std::string? Сколько будет "жить" эта stVar.
Вполне нормально. Часто делают так, что бы избежать лишних копирований:
class AAA < std::mapint, std::string> m; const std::string& find(int key) const < static const std::string empty; const std::mapint, std::string>::const_iterator i = m.find(key); if (m.end() != i) return *i; else return empty; > >;
Re[2]: Возврат std::string из функции
| От: | Аноним |
| Дата: | 29.12.06 10:41 |
| Оценка: |
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Аноним, Вы писали:
А>>
А>>////////////////////////////////////////////////////////////////////////// А>>std::string CXxxDlg::GetMyStr() А>>< А>> std::string stVar = "bla-bla-bla"; А>>
А>>Вопрос: Корректно ли возвращать так std::string? Сколько будет "жить" эта stVar.
А>Так почему сделать не хочешь?
Это просто примерю.
Re: Возврат std::string из функции
| От: | Centaur |
| Дата: | 29.12.06 11:00 |
| Оценка: |
Здравствуйте, Аноним, Вы писали:
А>Господа, есть следующая функция:
А>
А>////////////////////////////////////////////////////////////////////////// А>const std::string &CXxxDlg::GetMyStr() А> < А>static std::string stVar = "bla-bla-bla"; А>. А>. А> return stVar; А>> А>
А>Вопрос: Корректно ли возвращать так std::string? Сколько будет "жить" эта stVar.
Как объект — жить будет столько, сколько понадобится. То есть до скончания всей программы. Потому что static.
А вот как значение — будет жить только от одного вызова до другого. То есть, если функция решит в первый раз вернуть "bla-bla-bla", а во второй раз "abracadabra", то первый результат будет затёрт. И не дай б#г первому клиенту ещё держать указатель на данные первого результата, когда это произойдёт.
Re: Возврат std::string из функции
| От: | Sm0ke | ksi |
| Дата: | 29.12.06 11:07 | |
| Оценка: |
Здравствуйте, Аноним, Вы писали:
А>Всех с наступяющими праздниками.
А>Господа, есть следующая функция:
А>
А>////////////////////////////////////////////////////////////////////////// А>const std::string &CXxxDlg::GetMyStr() А> < А>static std::string stVar = "bla-bla-bla"; А>. А>. А> return stVar; А>> А>. А>std::string st = GetMyStr(); А>. А>
А>Вопрос: Корректно ли возвращать так std::string? Сколько будет "жить" эта stVar.
В многопоточном приложении будет работать не правильно.
Re: Возврат std::string из функции
| От: | Аноним |
| Дата: | 29.12.06 11:12 |
| Оценка: |
Здравствуйте, Аноним, Вы писали:
А>Всех с наступяющими праздниками.
А>Господа, есть следующая функция:
А>
А>////////////////////////////////////////////////////////////////////////// А>const std::string &CXxxDlg::GetMyStr() А> < А>static std::string stVar = "bla-bla-bla"; А>. А>. А> return stVar; А>> А>. А>std::string st = GetMyStr(); А>. А>
А>Вопрос: Корректно ли возвращать так std::string? Сколько будет "жить" эта stVar.
В принципе всё корректно. При вызове
std::string st = GetMyStr();
создаётся новый объёкт st в который копируется результат работы функции GetMyStr.
Сама stVar будет создана в момент запуска программы (до функции main)
и будет жить до её полного завешения. Порядок создания и разрушения таких объектов
зависит от порядка их объявления в тексте программы.
Re[2]: Возврат std::string из функции
| От: | demi |
| Дата: | 29.12.06 11:27 |
| Оценка: |
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Аноним, Вы писали:
А>>Всех с наступяющими праздниками.
Присоедиянюсь!
Разрешите подытожить:
-Корректно. Видимо сделано для устранения копирующего конструктора.
-Будут проблемы с многопоточностью. Вернуть string вместо string& — заморочек не будет.
-Возможны проблемы, если кто-то специально или случайно поменяет это строку там где этого не ожидается (писали выше).
Лично я бы так делать в 95% случаев не стал. Но есть 5%
Не стыдно попасть в дерьмо, стыдно в нём остаться!
Re: Возврат std::string из функции
| От: | ILva_ |
| Дата: | 29.12.06 11:28 |
| Оценка: |
Здравствуйте, Аноним, Вы писали:
А>Всех с наступяющими праздниками.
А>Господа, есть следующая функция:
А>
А>////////////////////////////////////////////////////////////////////////// А>const std::string &CXxxDlg::GetMyStr() А> < А>static std::string stVar = "bla-bla-bla"; А>. А>. А> return stVar; А>> А>. А>std::string st = GetMyStr(); А>. А>
А>Вопрос: Корректно ли возвращать так std::string? Сколько будет "жить" эта stVar.
Такой прием возможен и часто используется, как писали выше.
Но тут усть некие неприятные моменты.
Как известно, переменная stVar будет инициализированна 1 раз при первом вызове ф-ции и будет существовать до конца завершения программы.
Кто-нибудь может не разбираясь вставить в программу такой код:
std::string& myStr = const_cast(GetMyStr()); // теперь можно править статическую переменную myStr = "alb-alb-alb!";
Теперь все, кто позже обращался к этой ф-ции будут получать не то, что они ожидали:
std::string myStr2 = GetMyStr(); // вернет "alb-alb-alb!"
И все ссылки и указатели также изменятся.
Так что пользоваться надо аккуратно
Re[2]: Возврат std::string из функции
| От: | Аноним | |
| Дата: | 29.12.06 11:42 | |
| Оценка: | +1 | |
IL_>Кто-нибудь может не разбираясь вставить в программу такой код:
IL_>
IL_>std::string& myStr = const_cast(GetMyStr()); // теперь можно править статическую переменную IL_>myStr = "alb-alb-alb!"; IL_>
assert(stVar == "bla-bla-bla"); поможет отыскать таких умников
А вообще если ктото задасться целью развалить программу он это сможет сделать и по другому)
Re[3]: Возврат std::string из функции
| От: | Аноним |
| Дата: | 29.12.06 11:51 |
| Оценка: |
Здравствуйте, demi, Вы писали:
D>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, Аноним, Вы писали:
А>>>Всех с наступяющими праздниками.
D>Присоедиянюсь!
D>Разрешите подытожить:
D> -Корректно. Видимо сделано для устранения копирующего конструктора.
D> -Будут проблемы с многопоточностью. Вернуть string вместо string& — заморочек не будет.
D> -Возможны проблемы, если кто-то специально или случайно поменяет это строку там где этого не ожидается (писали выше).
D>Лично я бы так делать в 95% случаев не стал. Но есть 5%
Честно говоря не совсем понимаю какие могут быть проблемы с многопоточностью и с измененем строки.
1) При вызове:
std::string st = GetMyStr();
в стеке создается объект st и в него копируется строка ссылка на которую передаётся функцией GetMyStr.
Если после этого строку в GetMyStr изменить объект st этого уже не почуствует (у него уже есть копия).
Указанные Вами проблемы могут быть только при таком использовании:
std::string& st = GetMyStr();
или
std::string* st = &GetMyStr();
2) Вполне логично запретить изменение строки stVar вне функции GetMyStr
для этого её надо объявить так:
const std::string& GetMyStr();
Re[4]: Возврат std::string из функции
| От: | Аноним | |
| Дата: | 29.12.06 12:30 | |
| Оценка: | 2 (1) | |
Инициализация статической переменной в функции (вызов конструктора статической std:;string) происходит при первом вызове функции. C++ не гарантирует thread-safety сего действа. Так что если два потока одновременно вызовут функцию могут получится неприятные вещи. btw новые компилеры имеют спец опцию для thread-safe static'ов.
Re[5]: Возврат std::string из функции
| От: | Аноним |
| Дата: | 29.12.06 13:29 |
| Оценка: |
Здравствуйте, Аноним, Вы писали:
А>Инициализация статической переменной в функции (вызов конструктора статической std:;string) происходит при первом вызове функции. C++ не гарантирует thread-safety сего действа. Так что если два потока одновременно вызовут функцию могут получится неприятные вещи. btw новые компилеры имеют спец опцию для thread-safe static'ов.
Да это так.
Как Вы думаете, спасёт в данном случае что-то вроде:
const std::string GetMyStr()
static std::string* pVar;
lock();
static std::string stVar = "bla-bla-bla";
pVar = &stVar;
. каие-то операции над stVar;
А в случае если stVar никогда не меняется следует вообще написать:
const char* GetMyStr()
return "bla-bla-bla";
>
Re[3]: Возврат std::string из функции
| От: | Аноним |
| Дата: | 30.12.06 11:01 |
| Оценка: |
Т.е. я как понял. Имея следующую функцию:
const std::string &CXxxDlg::GetMyStr(int nIdx) < static std::string stVar; switch(nIdx) < case 1: stVar = "aaaaaaaaa"; break; case2: stVar = "bbbbbbbbb"; break; default: stVar = "ccccccccc"; break; > return stVar; >
Совершенно корректно использовать её в _однопоточном_ приложении таким образом:
. std::string st1 = GetMyStr(1); . . std::string st2 = GetMyStr(999); . . std::string st3 = GetMyStr(2); .
Правильно?
ЗЫ. Но приложение у меня не однопоточное, какие могут быть глюки. И что можно с ними сделать?
Re[2]: Возврат std::string из функции
| От: | IROV.. | |
| Дата: | 30.12.06 12:46 | |
| Оценка: | 1 (1) | |
Здравствуйте, remark, Вы писали:
R>Вполне нормально. Часто делают так, что бы избежать лишних копирований:
R>
R>class AAA R> < R>std::mapint, std::string> m; R> const std::string& find(int key) const R> < R>static const std::string empty; R> const std::mapint, std::string>::const_iterator i = m.find(key); R> if (m.end() != i) R> return *i; R> else R> return empty; R> > R>>; R>
Я для этого создал даже такую функцию..
я не волшебник, я только учусь!
Re[4]: Возврат std::string из функции
| От: | Аноним |
| Дата: | 30.12.06 12:48 |
| Оценка: |
А>ЗЫ. Но приложение у меня не однопоточное, какие могут быть глюки. И что можно с ними сделать?
Обычные такие глюки. Мусор в строках, крэши, вобщем ниче необычного
Ваш код по глюкам в MT аналогичен следующему:
std::string stVar; const std::string &CXxxDlg::GetMyStr(int nIdx) < switch(nIdx) < case 1: stVar = "aaaaaaaaa"; break; case2: stVar = "bbbbbbbbb"; break; default: stVar = "ccccccccc"; break; >return stVar; >
C++: Возврат значений
Функции, которые мы определяли в предыдущих уроках, заканчивали свою работу тем, что печатали на экран какие-то данные:
void Greating() < std::cout int main()
Пользы от таких функций не очень много, так как результатом их работы невозможно воспользоваться внутри программы.
В этом уроки мы рассмотрим, как сделать наши функции полезными.
Возвращаемые значения
Когда мы пишем пользовательскую функцию, мы можем определить, будет ли она возвращать значение вызывающей стороне или нет.
Чтобы вернуть значение вызывающей стороне, необходимы две вещи:
- Функция должна указать, значение какого типа будет возвращено. Это делается путем установки типа возвращаемого значения функции, который является типом, определенным перед именем функции
- Внутри функции, которая будет возвращать значение, используем инструкцию return . Это нужно, чтобы указать конкретное значение, возвращаемое вызывающей стороне. Конкретное значение, возвращаемое функцией, называется возвращаемым значением. Когда инструкция return выполняется, возвращаемое значение копируется из функции обратно в вызывающую функцию. Этот процесс называется возвратом по значению
Общий вид функции:
имя функции(аргументы)
Рассмотрим простую функцию, которая возвращает строку. Также пример программы, которая ее вызывает:
#include #include // функция возвращает строку, поэтому тип возвращаемого значения std::string std::string GetDomain() < return "Hexlet"; >int main() < std::cout
Выполнение начинается с верхней части main . В первой же инструкции происходит вызов функции GetDomain() . В результате она возвращает конкретное значение Hexlet обратно вызывающей стороне, которое затем выводится в консоль через std::cout.
Любой код после return не выполняется:
int sum()
Возвращать можно не только конкретное значение. Так как return работает с выражениями, справа от него может появиться почти все что угодно. Здесь нужно руководствоваться принципами читаемости кода:
#include std::string GetDomain() < std::string domain < "Hexlet" >; return domain; >
Здесь мы не возвращаем переменную. Возвращается всегда значение, которое находится в этой переменной. Ниже пример с вычислениями:
int sum()
Здесь сначала будет произведено вычисление, а затем результат мы вернем из функции.
Отсутствие возвращаемого значения
Функции не обязаны возвращать значение. Чтобы сообщить компилятору, что функция не возвращает значение, используется тип возвращаемого значения void .
Посмотрим на функцию Greating() :
#include void Greating()
Эта функция имеет тип возвращаемого значения void . Это указывает на то, что она не возвращает значение вызывающей стороне.
Возврат значения из main
Теперь у нас есть концептуальные инструменты, чтобы понять, как работает функция main .
Когда программа выполняется, операционная система вызывает функцию main . Инструкции в main выполняются последовательно.
Также main возвращает целочисленное значение — обычно 0, и программа завершается. Значение, возвращаемое из main , называют кодом возврата. По нему судят об успешности выполнения программы.
Задание
Реализуйте функцию SayHurrayThreeTimes() , которая возвращает строку "hurray! hurray! hurray!".
Упражнение не проходит проверку — что делать?
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
- Обязательно приложите вывод тестов, без него практически невозможно понять что не так, даже если вы покажете свой код. Программисты плохо исполняют код в голове, но по полученной ошибке почти всегда понятно, куда смотреть.
В моей среде код работает, а здесь нет
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Мой код отличается от решения учителя
Это нормально , в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Прочитал урок — ничего не понятно
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.
Полезное
- std::string
- Завершение программы С++