лучший способ вернуть std :: string, локальную для функции
В C ++ как лучше всего вернуть локальную переменную std :: string из функции?
7 ответов
Нет, это не правда. Даже если mystring вышел за пределы области видимости и был уничтожен, ret имеет копию mystring, поскольку функция MyFunc возвращается по значению.
Возникнет проблема, если ваш код выглядит так:
Итак, то, как вы это написали, в порядке. Только один совет — если вы можете построить такую строку, я имею в виду — вы можете сделать это в одной строке, иногда лучше делать это так:
Или, если это посложнее, например:
Это даст вашему компилятору подсказку , что нужно больше оптимизировать, чтобы он мог сделать на одну копию вашей строки меньше (RVO).
Как уже упоминалось, копируется std :: string. Таким образом, даже исходная локальная переменная вышла за пределы области видимости, вызывающий получает копию std :: string.
Я думаю, что чтение на RVO может полностью избавить вас от путаницы. В данном случае это точно называется NRVO (Named RVO), но по сути тот же.
Дополнительное чтение : проблема с использованием RVO в том, что это не самая гибкая вещь в мире. Одна из главных проблем C ++ 0x — это ссылки на rvalue, которые призваны решить эту проблему. .
Ты пробовал это? При возврате строка копируется. Что ж, это официальная версия, на самом деле копия, вероятно, оптимизирована, но в любом случае ее можно использовать.
Что ж, ret будет иметь значение mystring после MyFunc (). В случае возврата результата по значению создается временный объект путем копирования локального.
На мой взгляд, в этих разделах C ++ FAQ Lite.
Это зависит от варианта использования. Если экземпляр должен нести ответственность за строку, строки должны возвращаться константной ссылкой. Проблема в том, что делать, если нет объекта, который нужно вернуть. С помощью указателей о недопустимом объекте можно было бы сообщить с помощью 0. Такой «нулевой объект» также можно использовать со ссылками (например, NullString во фрагменте кода).
Конечно, лучший способ сообщить о недопустимом возвращаемом значении — это выбросить исключения.
Другой вариант использования — если ответственность за строку передается вызывающему. В этом случае следует использовать auto_ptr . В приведенном ниже коде показаны все эти варианты использования.
Ни один из предыдущих ответов не содержал здесь ключевого понятия . Это понятие семантика перемещения . Класс std::string имеет конструктор move , что означает, что он имеет семантику перемещения . Семантика перемещения подразумевает, что объект не копируется в другое место при возврате функции, что обеспечивает более быстрое выполнение функции.
Попробуйте выполнить пошаговую отладку в функции, которая возвращает std::string , и исследуйте внутренности того объекта, который вот-вот должен быть возвращен. Вы увидите адрес указателя поля члена xxx . Затем проверьте переменную std::string , которая получила возвращаемое функцией значение. Вы увидите тот же адрес указателя xxx в этом объекте.
Это означает, что копирования не было , дамы и господа. Это семантика хода , да благословит Бог Америку!
Возврат строки C из функции
Я пытаюсь вернуть строку C из функции, но она не работает. Вот мой код.
в основном я называю это так:
Я также пробовал некоторые другие способы myFunction но они не работают. Например:
Примечание: мне не разрешено использовать указатели!
немного фона по этой проблеме: Есть функция, которая выясняет, какой месяц это e.g; если его 1, то он возвращает январь etc так далее.
поэтому, когда он собирается печатать, он делает вот так. printf(«Month: %s»,calculateMonth(month)); . Теперь проблема в том, как вернуть эту строку из
12 ответов
ваша подпись функции должна быть:
Edit:
Справочная информация:
прошли годы с тех пор, как этот пост и никогда не думал, что он будет проголосован, потому что это так важно для C & C++. Тем не менее следует продолжить обсуждение.
в C (& C++, если на то пошло) строка — это просто массив байтов, заканчивающийся нулевым байтом, поэтому термин «string-zero» используется для представьте этот особый аромат струн. Существуют и другие типы строк, но в C (& C++) этот вкус по своей сути понимается самим языком. Другие языки (Java, Pascal и т. д.) используют разные методологии для понимания «моей строки».
если вы когда-либо используете Windows API (который находится в C++), вы увидите довольно регулярно параметры функции, такие как: «LPCSTR lpszName». Часть » sz «представляет это понятие » string-zero»: массив байтов с нулевым значением (/zero) терминатор.
пояснение:
ради этого «вступления» я использую слово «байты» и «символы» взаимозаменяемо, потому что так легче учиться. Имейте в виду, что существуют другие методы (широкие символы и многобайтовые символьные системы-mbcs), которые используются для работы с международными символами. UTF-8 является примером mbcs. Ради вступления, я тихо «пропускаю» все этот.
память:
это означает, что строка типа «моя строка» фактически использует 9+1 (=10!) байты. Это важно знать, когда Вы, наконец, доберетесь до динамического распределения строк. Так, без этого завершающего нуля’, у вас нет строки. У вас есть массив символов (также называемый буфером), висящий в памяти.
долговечность данных:
использование функции this путь:
. как правило, вы будете приземляться со случайными необработанными исключениями / ошибками сегмента и тому подобное, особенно «по дороге».
короче говоря, хотя мой ответ верен — 9 раз из 10 вы в конечном итоге с программой, которая падает, если вы используете его таким образом, особенно если вы думаете, что это «хорошая практика», чтобы сделать это таким образом. Короче говоря, это вообще не так.
например, представьте себе некоторое время в будущем, строка теперь должна быть обработана в некотором роде. Как правило, кодер «выбирает легкий путь» и (пытается) написать код следующим образом:
то есть ваша программа аварийно завершит работу, потому что компилятор (может/не может) освободил память, используемую szBuffer времени printf() на main() называется. (Ваш компилятор также должен предупредить вас о таких проблемах заранее).
есть два способа вернуть строки, которые не будут рвать так легко.
- возвращающ буферы (статические или динамически выделенные), которые живут некоторое время. В C++ используйте «вспомогательные классы» (например. std::string ) для обработки долговечности данных (что требует изменения возвращаемого значения функции) или
- передайте буфер функции, которая заполняется информацией.
обратите внимание, что невозможно использовать строки без использования указателей в C. Как я показал, они являются синонимами. Даже в C++ с классами шаблонов всегда есть буферы (т. е. указатели), используемые в фон.
Итак, чтобы лучше ответить на (Теперь измененный вопрос). (наверняка есть множество «других ответов», которые могут быть предоставлены).
Более Безопасные Ответы:
, например 1. использование статически выделенных строк:
что делает здесь «статический» (многим программистам не нравится этот тип «распределения»), так это то, что строки помещаются в сегмент данных программы. То есть, это навсегда распределяемый.
если вы перейдете на C++ ,вы будете использовать аналогичные стратегии:
. но, вероятно, проще использовать вспомогательные классы, такие как std::string , если вы пишете код для собственного использования (а не часть библиотеки для совместного использования с другими).
например 2. использование буферов, определенных вызывающим абонентом:
это более «дурак доказательство» способ передачи строк вокруг. Возвращаемые данные не подлежат обработке вызывающей стороной. То есть, например 1 можно легко злоупотреблять вызывающей стороной и привести к сбоям в приложении. Таким образом, это намного безопаснее (хотя и использует больше строк кода):
есть много причин, почему 2-й метод лучше, особенно если вы пишете библиотеку, которая будет использоваться другими (Вам не нужно блокировать определенную схему распределения/освобождения, третьи стороны не могут сломать ваш код, вам не нужно ссылаться на определенную библиотеку управления памятью), но, как и весь код, это зависит от вас что тебе больше всего нравится. По этой причине большинство людей выбирают, например, 1, пока они не были сожжены так много раз, что они отказываются писать так больше 😉
отказ от ответственности:
Я вышел на пенсию несколько лет назад, и мой C немного заржавел. Этот демо-код должен правильно компилироваться с помощью C (это нормально для любого компилятора C++).
Как я могу вернуть строковое значение из функции в С++
Разоблачение строки cout фактически отображает значение. Но я не могу вернуть значение в строке.
Честно говоря, я понятия не имею, почему это не работает. Я изначально просто хотел использовать “char”, но по какой-то причине это не работает.
Visual Studio не понравилось:
На данный момент я просто хочу вернуть строковое значение из функции. Там больше, что мне нужно, но это главная проблема прямо сейчас.
Разоблачение строки cout фактически отображает строку. Но не возвращать строку.
Ваша программа печатает и возвращает строку, снова печатая ее в main . Единственные проблемы, которые я вижу с вашей программой:
- Вы используете system(«pause») без причины.
- Вы не согласны с использованием либо std:: prefix, либо импорта пространства имен. В связи с этим я настоятельно рекомендую префикс std:: .
- Вы не используете аргумент функции.
Я изначально просто хотел использовать “char”, но по какой-то причине это не работает.
Ну, char , как следует из названия, может хранить только 1 символ. В:
вы пытаетесь присвоить 5 символов (4 + \0 ) объектам, размер которых может хранить только 1. Это причина, по которой ваш компилятор жаловался.
Я думаю, вам нужно передать int в вашу функцию и вернуть ее в строковой форме. Чтобы сделать это преобразование, вам нужно что-то вроде этого:
Если вы поместите этот фрагмент в функцию, вы также можете принять параметр int, преобразовать его в std :: string и вернуть std :: string, как показали другие.
Вам нужно объявить возвращаемый тип функции как std::string а затем вернуть либо строковый объект, то, что можно неявно преобразовать в строковый объект или что-то, что явно создает объект string.
Также обратите внимание, что строки в стиле C имеют тип char* (строки в стиле C – это в основном массив chars , причем последний элемент равен \0 , то есть 0).
Ваш код работает отлично, хотя system(«pause») полностью избыточна и бессмысленна и должна быть удалена. На самом деле это может ввести вас в замешательство.