Вместо: char * writable = new char [str.size () + 1]; Вы можете использовать char writeable [str.size () + 1]; Тогда вам не нужно беспокоиться об удалении доступных для записи или обработки исключений.
7
Вы не можете использовать str.size (), если размер не известен во время компиляции, также он может переполнить ваш стек, если значение фиксированного размера огромно.
Нет, но char* dest = new char[str.length() + 1]; std::copy(str.begin(), str.end(), dest)был бы более идиоматическим C ++. strcpy()и malloc()не ошибаются и не проблематичны, но кажется непоследовательным использование строки C ++ и средств библиотеки C с эквивалентами C ++ в одном и том же блоке кода.
Бойси
Ответы:
1057
Если вы просто хотите передать std::stringнужную функцию, const char*вы можете использовать
std::string str;constchar* c = str.c_str();
Если вы хотите получить доступную для записи копию, например char *, вы можете сделать это с помощью этого:
std::string str;char* writable =newchar[str.size()+1];
std::copy(str.begin(), str.end(), writable);
writable[str.size()]='\0';// don't forget the terminating 0// don't forget to free the string after finished using itdelete[] writable;
Изменить : обратите внимание, что выше не является безопасным для исключения. Если что-то между newвызовом и deleteвызовом выбрасывается, вы потеряете память, так как ничто не вызовет deleteвас автоматически. Есть два непосредственных способа решить это.
повышение :: scoped_array
boost::scoped_array удалит память для вас после выхода из области видимости:
std::string str;
boost::scoped_array<char> writable(newchar[str.size()+1]);
std::copy(str.begin(), str.end(), writable.get());
writable[str.size()]='\0';// don't forget the terminating 0// get the char* using writable.get()// memory is automatically freed if the smart pointer goes // out of scope
станд :: вектор
Это стандартный способ (не требует никакой внешней библиотеки). Вы используете std::vector, который полностью управляет памятью для вас.
std::string str;
std::vector<char> writable(str.begin(), str.end());
writable.push_back('\0');// get the char* using &writable[0] or &*writable.begin()
Просто используйте char * result = strdup (str.c_str ());
Джаспер Беккерс
63
можно, но strdup - это не стандартная функция ac или c ++, а из posix :)
Йоханнес Шауб - litb
14
то, что я бы предпочел, как правило, это std :: vector <char> writable (str.begin (), str.end ()); writable.push_back ( '\ 0'); char * c = & доступный для записи [0];
Йоханнес Шауб -
17
std :: copy - это способ сделать это на языке C ++ без необходимости использовать указатель на строку. Я стараюсь избегать использования функций C, насколько я могу.
Йоханнес Шауб -
16
Начиная с C ++ 17, std::string::data()теперь возвращает CharT*вместо a const CharT*. Это может быть хорошей идеей, чтобы обновить этот ответ :)
Rakete1111
192
Дано сказать ...
std::string x ="hello";
Получение `char *` или `const char *` из `строки`
Как получить указатель на символ, который действителен, пока xостается в области видимости и больше не изменяется
C ++ 11 упрощает вещи; следующие все дают доступ к одному и тому же внутреннему строковому буферу:
constchar* p_c_str = x.c_str();constchar* p_data = x.data();char* p_writable_data = x.data();// for non-const x from C++17 constchar* p_x0 =&x[0];char* p_x0_rw =&x[0];// compiles iff x is not const...
Все вышеперечисленные указатели будут содержать одно и то же значение - адрес первого символа в буфере. Даже пустая строка имеет «первый символ в буфере», потому что C ++ 11 гарантирует всегда сохранять дополнительный символ-терминатор NUL / 0 после явно назначенного содержимого строки (например, std::string("this\0that", 9)будет содержать буфер "this\0that\0").
Учитывая любой из вышеперечисленных указателей:
char c = p[n];// valid for n <= x.size()// i.e. you can safely read the NUL at p[x.size()]
Только для не constуказателя p_writable_dataи от &x[0]:
p_writable_data[n]= c;
p_x0_rw[n]= c;// valid for n <= x.size() - 1// i.e. don't overwrite the implementation maintained NUL
Дать NUL в другом месте в строке ничего не изменить string«s size(); stringРазрешается содержать любое количество NUL - им не предоставляется особая обработка std::string(то же самое в C ++ 03).
В C ++ 03 все было значительно сложнее ( выделены ключевые различия ):
x.data()
возвращает const char*во внутренний буфер строки, который не требовался Стандартом для завершения с NUL (т. е. может ['h', 'e', 'l', 'l', 'o']сопровождаться неинициализированными или мусорными значениями со случайным доступом к нему с неопределенным поведением ).
x.size()символы безопасны для чтения, то есть x[0]черезx[x.size() - 1]
для пустых строк вам гарантирован некоторый ненулевой указатель, к которому можно безопасно добавить 0 (ура!), но вы не должны разыменовывать этот указатель.
&x[0]
для пустых строк это имеет неопределенное поведение (21.3.4)
например, учитывая, что f(const char* p, size_t n) { if (n == 0) return; ...whatever... }вы не должны звонить, f(&x[0], x.size());когда x.empty()- просто используйте f(x.data(), ...).
в противном случае, x.data()но согласно :
для не- constxэто дает не constchar*указатель; Вы можете перезаписать содержимое строки
x.c_str()
возвращает const char*ASCIIZ (NUL-оканчивающееся) представление значения (то есть ['h', 'e', 'l', 'l', 'o', '\ 0']).
хотя немногие, если какие-либо реализации решили сделать это, стандарт C ++ 03 был сформулирован так, чтобы позволить строковой реализации свободно создавать отдельный NUL-концевой буфер на лету из потенциально не-NUL-концевого буфера, «выставляемого» x.data()и&x[0]
x.size() +1 символы безопасны для чтения.
гарантировано безопасно даже для пустых строк (['\ 0']).
Последствия доступа к внешним правовым индексам
Какой бы способ вы ни указали, вы не должны получать доступ к памяти дальше от указателя, чем символы, гарантированно присутствующие в описаниях выше. Попытки сделать это имеют неопределенное поведение , с очень реальной вероятностью сбоев приложений и результатов мусора даже для операций чтения, а также оптовых данных, повреждения стека и / или уязвимостей безопасности для записей.
Когда эти указатели становятся недействительными?
Если вы вызываете какую-либо stringфункцию-член, которая изменяет stringили резервирует дополнительную емкость, любые значения указателя, предварительно возвращенные любым из вышеуказанных методов, становятся недействительными . Вы можете использовать эти методы снова, чтобы получить другой указатель. (Правила те же, что и для итераторов в strings).
См. Также Как сделать указатель символа действительным даже после того, как xпокидает область видимости или изменяется далее ниже ....
Итак, что лучше использовать?
Начиная с C ++ 11, используйте .c_str()для данных ASCIIZ и .data()для «двоичных» данных (объяснено ниже).
В C ++ 03, использование , .c_str()если уверены , что .data()достаточно, и предпочитают .data()более , &x[0]как это безопасно для пустых строк ....
... попытайтесь понять программу достаточно, чтобы использовать ее, data()когда это уместно, иначе вы, вероятно, допустите другие ошибки ...
Символ ASCII NUL '\ 0', гарантируемый символом, .c_str()используется многими функциями в качестве контрольного значения, обозначающего конец соответствующих и безопасных для доступа данных. Это относится как к C ++ - только функциям, таким как say, так fstream::fstream(const char* filename, ...)и к функциям shared-with-C, таким как strchr(), и printf().
Учитывая, что .c_str()гарантии возвращаемого буфера в C ++ 03 являются супер-набором .data(), вы всегда можете безопасно его использовать .c_str(), но люди иногда этого не делают, потому что:
Использование .data()сообщает другим программистам, читающим исходный код, что данные не являются ASCIIZ (скорее, вы используете строку для хранения блока данных (который иногда даже не является действительно текстовым)), или что вы передаете его другая функция, которая обрабатывает его как блок «двоичных» данных. Это может быть критически важным для обеспечения того, чтобы изменения кода других программистов продолжали правильно обрабатывать данные.
Только C ++ 03: есть небольшая вероятность того, что вашей stringреализации потребуется дополнительное выделение памяти и / или копирование данных для подготовки буфера с NUL-ограничением
В качестве еще одной подсказки, если для параметров функции требуется ( const), char*но они не настаивают на получении x.size(), функция, вероятно, нуждается в вводе ASCIIZ, так .c_str()что это хороший выбор (функция должна знать, где текст заканчивается каким-то образом, так что если это не так В качестве отдельного параметра это может быть только соглашение, такое как префикс длины или часовой или некоторая фиксированная ожидаемая длина).
Как сделать указатель на символ действительным даже после того, как xпокидает область видимости или изменяется дальше
Вам нужно будет скопировать содержимое в stringxновую область памяти снаружи x. Этот внешний буфер может находиться во многих местах, например в другой stringпеременной или переменной массива символов, он может иметь или не иметь другое время жизни, отличное от того, xчто находится в другой области видимости (например, пространство имен, глобальное, статическое, куча, общая память, файл отображения памяти) ,
Чтобы скопировать текст из std::string xв отдельный массив символов:
// USING ANOTHER STRING - AUTO MEMORY MANAGEMENT, EXCEPTION SAFE
std::string old_x = x;// - old_x will not be affected by subsequent modifications to x...// - you can use `&old_x[0]` to get a writable char* to old_x's textual content// - you can use resize() to reduce/expand the string// - resizing isn't possible from within a function passed only the char* address
std::string old_x = x.c_str();// old_x will terminate early if x embeds NUL// Copies ASCIIZ data but could be less efficient as it needs to scan memory to// find the NUL terminator indicating string length before allocating that amount// of memory to copy into, or more efficient if it ends up allocating/copying a// lot less content.// Example, x == "ab\0cd" -> old_x == "ab".// USING A VECTOR OF CHAR - AUTO, EXCEPTION SAFE, HINTS AT BINARY CONTENT, GUARANTEED CONTIGUOUS EVEN IN C++03
std::vector<char> old_x(x.data(), x.data()+ x.size());// without the NUL
std::vector<char> old_x(x.c_str(), x.c_str()+ x.size()+1);// with the NUL// USING STACK WHERE MAXIMUM SIZE OF x IS KNOWN TO BE COMPILE-TIME CONSTANT "N"// (a bit dangerous, as "known" things are sometimes wrong and often become wrong)char y[N +1];
strcpy(y, x.c_str());// USING STACK WHERE UNEXPECTEDLY LONG x IS TRUNCATED (e.g. Hello\0->Hel\0)char y[N +1];
strncpy(y, x.c_str(), N);// copy at most N, zero-padding if shorter
y[N]='\0';// ensure NUL terminated// USING THE STACK TO HANDLE x OF UNKNOWN (BUT SANE) LENGTHchar* y = alloca(x.size()+1);
strcpy(y, x.c_str());// USING THE STACK TO HANDLE x OF UNKNOWN LENGTH (NON-STANDARD GCC EXTENSION)char y[x.size()+1];
strcpy(y, x.c_str());// USING new/delete HEAP MEMORY, MANUAL DEALLOC, NO INHERENT EXCEPTION SAFETYchar* y =newchar[x.size()+1];
strcpy(y, x.c_str());// or as a one-liner: char* y = strcpy(new char[x.size() + 1], x.c_str());// use y...delete[] y;// make sure no break, return, throw or branching bypasses this// USING new/delete HEAP MEMORY, SMART POINTER DEALLOCATION, EXCEPTION SAFE// see boost shared_array usage in Johannes Schaub's answer// USING malloc/free HEAP MEMORY, MANUAL DEALLOC, NO INHERENT EXCEPTION SAFETYchar* y = strdup(x.c_str());// use y...
free(y);
Другие причины, чтобы хотеть char*или const char*порожденный изstring
Итак, выше вы видели, как получить ( const) char*и как сделать копию текста независимой от оригинала string, но что вы можете с этим сделать ? Случайная выборка примеров ...
дать коду "C" доступ к stringтексту C ++ , как вprintf("x is '%s'", x.c_str());
скопируйте xтекст в буфер, указанный вызывающей стороной вашей функции (например strncpy(callers_buffer, callers_buffer_size, x.c_str())), или в энергозависимую память, используемую для ввода-вывода устройства (например for (const char* p = x.c_str(); *p; ++p) *p_device = *p;)
добавить xтекст в массив символов, уже содержащий некоторый текст ASCIIZ (например strcat(other_buffer, x.c_str())) - будьте осторожны, чтобы не переполнить буфер (во многих ситуациях вам может понадобиться использовать strncat)
вернуть a const char*или char*функцию (возможно, по историческим причинам - клиент использует ваш существующий API - или для совместимости с C вы не хотите возвращать a std::string, но действительно хотите скопировать свои stringданные куда-нибудь для вызывающей стороны)
будьте осторожны, чтобы не вернуть указатель, который может быть разыменован вызывающей стороной после того, как локальная stringпеременная, на которую указывает этот указатель, вышла из области видимости
некоторые проекты с общими объектами, скомпилированными / связанными для разных std::stringреализаций (например, STLport и compiler-native), могут передавать данные как ASCIIZ, чтобы избежать конфликтов
Хороший. Другая причина хотеть char * (не const) состоит в том, чтобы работать с широковещательной передачей MPI. Это выглядит лучше, если вам не нужно копировать туда-сюда. Я бы лично предложил get * const get для string. Const указатель, но редактируемая строка. Хотя, возможно, это не
совсем верно:
33
Используйте .c_str()метод для const char *.
Вы можете использовать &mystring[0]для получения char *указателя, но есть несколько хитростей: вы не обязательно получите строку с нулевым символом в конце и вы не сможете изменить размер строки. Вы должны быть особенно осторожны, чтобы не добавлять символы после конца строки, иначе вы получите переполнение буфера (и возможное падение).
Не было никакой гарантии, что все символы будут частью одного и того же непрерывного буфера до C ++ 11, но на практике все известные реализации std::stringработали так или иначе; см. «& s [0]» указывает на смежные символы в std :: string? ,
Обратите внимание, что многие stringфункции-члены перераспределяют внутренний буфер и делают недействительными любые указатели, которые вы могли сохранить. Лучше всего использовать их сразу, а затем отказаться.
Вы должны заметить, что data () возвращает const char * :), что вы имеете в виду, & str [0], который возвращает непрерывную, но не обязательную строку с нулевым символом в конце.
Йоханнес Шауб -
1
@litb, аааа! Это то, что я получаю за попытку быстрого ответа. Я использовал ваше решение в прошлом, не знаю, почему это не первое, что пришло в голову. Я отредактировал свой ответ.
Марк Рэнсом
2
Технически, хранилище std :: string будет смежным только в C ++ 0x.
MSalters
1
@MSalters, спасибо - я этого не знал. Мне было бы трудно найти реализацию, где это было бы не так.
Возвращает: указатель p такой, что p + i == & оператор для каждого i в [0, size ()].
CharT const * от std::basic_string<CharT>
std::string const cstr ={"..."};charconst* p = cstr.data();// or .c_str()
CharT * от std::basic_string<CharT>
std::string str ={"..."};char* p = str.data();
C ++ 11
CharT const * от std::basic_string<CharT>
std::string str ={"..."};
str.c_str();
CharT * от std::basic_string<CharT>
Начиная с C ++ 11, стандарт гласит:
Символоподобные объекты в basic_stringобъекте должны храниться непрерывно. То есть для любого basic_stringобъекта sидентичность &*(s.begin() + n) == &*s.begin() + nдолжна сохраняться для всех значений nтакого, что 0 <= n < s.size().
void aFunctionAPI(char* input);// other stuff
aFunctionAPI("Foo");//this call is not safe. if the function modified the //literal string the program will crash
std::string myFoo("Foo");
aFunctionAPI(myFoo.c_str());//this is not compiling
aFunctionAPI(const_cast<char*>(myFoo.c_str()));//this is not safe std::string //implement reference counting and //it may change the value of other//strings as well.DeepString myDeepFoo(myFoo);
aFunctionAPI(myFoo.str());//this is fine
Я назвал класс, DeepStringпотому что он создает глубокую и уникальную копию ( DeepStringне копируемую) существующей строки.
Я бы избежал этого соглашения об именах. c_str()используется stdкак «C-string», а не «const string» и str()всегда возвращает a std::basic_string, а не char*(например std::stringstream::str())
bcrist
8
char* result = strcpy((char*)malloc(str.length()+1), str.c_str());
выглядит причудливо, но очень трудно понять ... Простое - лучшая ИМО
Наим А. Малик
4
strcpy (), malloc (), length () и c_str () являются основными функциями, и в этом нет ничего сложного. Просто выделяю память и копирую.
cegprakash
5
да, функции являются базовыми, но вы скрутили и согнули их, чтобы они выглядели как миска спагетти или монстр Франкенштейна с одним вкладышем :)
Наим А. Малик
4
Да, функции являются основными, но ... вы помните, когда начинали работать с языком программирования? Несколько строк, которые нужно объяснить, и это действительно поможет новичку понять, почему, например, он отличается от этого ответа или лучше :)
Hastur
2
@cegprakash: всякий раз, когда есть malloc (), также должен быть free (). В противном случае код утечки памяти, и решение в вашем ответе тоже. Распределение памяти, по крайней мере, не намекая на требуемое освобождение, является плохой практикой для таких вопросов.
Привет, то, что ты написал, уже было сказано несколько раз, с более подробной информацией, в других ответах на 5-летний вопрос. Можно ответить на старые вопросы, но только если вы добавите новую информацию. В противном случае это просто шум.
strcpy
иmalloc
не совсем C ++.char* dest = new char[str.length() + 1]; std::copy(str.begin(), str.end(), dest)
был бы более идиоматическим C ++.strcpy()
иmalloc()
не ошибаются и не проблематичны, но кажется непоследовательным использование строки C ++ и средств библиотеки C с эквивалентами C ++ в одном и том же блоке кода.Ответы:
Если вы просто хотите передать
std::string
нужную функцию,const char*
вы можете использоватьЕсли вы хотите получить доступную для записи копию, например
char *
, вы можете сделать это с помощью этого:Изменить : обратите внимание, что выше не является безопасным для исключения. Если что-то между
new
вызовом иdelete
вызовом выбрасывается, вы потеряете память, так как ничто не вызоветdelete
вас автоматически. Есть два непосредственных способа решить это.повышение :: scoped_array
boost::scoped_array
удалит память для вас после выхода из области видимости:станд :: вектор
Это стандартный способ (не требует никакой внешней библиотеки). Вы используете
std::vector
, который полностью управляет памятью для вас.источник
std::string::data()
теперь возвращаетCharT*
вместо aconst CharT*
. Это может быть хорошей идеей, чтобы обновить этот ответ :)Дано сказать ...
Получение `char *` или `const char *` из `строки`
Как получить указатель на символ, который действителен, пока
x
остается в области видимости и больше не изменяетсяC ++ 11 упрощает вещи; следующие все дают доступ к одному и тому же внутреннему строковому буферу:
Все вышеперечисленные указатели будут содержать одно и то же значение - адрес первого символа в буфере. Даже пустая строка имеет «первый символ в буфере», потому что C ++ 11 гарантирует всегда сохранять дополнительный символ-терминатор NUL / 0 после явно назначенного содержимого строки (например,
std::string("this\0that", 9)
будет содержать буфер"this\0that\0"
).Учитывая любой из вышеперечисленных указателей:
Только для не
const
указателяp_writable_data
и от&x[0]
:Дать NUL в другом месте в строке ничего не изменить
string
«ssize()
;string
Разрешается содержать любое количество NUL - им не предоставляется особая обработкаstd::string
(то же самое в C ++ 03).В C ++ 03 все было значительно сложнее ( выделены ключевые различия ):
x.data()
const char*
во внутренний буфер строки, который не требовался Стандартом для завершения с NUL (т. е. может['h', 'e', 'l', 'l', 'o']
сопровождаться неинициализированными или мусорными значениями со случайным доступом к нему с неопределенным поведением ).x.size()
символы безопасны для чтения, то естьx[0]
черезx[x.size() - 1]
&x[0]
f(const char* p, size_t n) { if (n == 0) return; ...whatever... }
вы не должны звонить,f(&x[0], x.size());
когдаx.empty()
- просто используйтеf(x.data(), ...)
.x.data()
но согласно :const
x
это дает неconst
char*
указатель; Вы можете перезаписать содержимое строкиx.c_str()
const char*
ASCIIZ (NUL-оканчивающееся) представление значения (то есть ['h', 'e', 'l', 'l', 'o', '\ 0']).x.data()
и&x[0]
x.size()
+1 символы безопасны для чтения.Последствия доступа к внешним правовым индексам
Какой бы способ вы ни указали, вы не должны получать доступ к памяти дальше от указателя, чем символы, гарантированно присутствующие в описаниях выше. Попытки сделать это имеют неопределенное поведение , с очень реальной вероятностью сбоев приложений и результатов мусора даже для операций чтения, а также оптовых данных, повреждения стека и / или уязвимостей безопасности для записей.
Когда эти указатели становятся недействительными?
Если вы вызываете какую-либо
string
функцию-член, которая изменяетstring
или резервирует дополнительную емкость, любые значения указателя, предварительно возвращенные любым из вышеуказанных методов, становятся недействительными . Вы можете использовать эти методы снова, чтобы получить другой указатель. (Правила те же, что и для итераторов вstring
s).См. Также Как сделать указатель символа действительным даже после того, как
x
покидает область видимости или изменяется далее ниже ....Итак, что лучше использовать?
Начиная с C ++ 11, используйте
.c_str()
для данных ASCIIZ и.data()
для «двоичных» данных (объяснено ниже).В C ++ 03, использование ,
.c_str()
если уверены , что.data()
достаточно, и предпочитают.data()
более ,&x[0]
как это безопасно для пустых строк ....... попытайтесь понять программу достаточно, чтобы использовать ее,
data()
когда это уместно, иначе вы, вероятно, допустите другие ошибки ...Символ ASCII NUL '\ 0', гарантируемый символом,
.c_str()
используется многими функциями в качестве контрольного значения, обозначающего конец соответствующих и безопасных для доступа данных. Это относится как к C ++ - только функциям, таким как say, такfstream::fstream(const char* filename, ...)
и к функциям shared-with-C, таким какstrchr()
, иprintf()
.Учитывая, что
.c_str()
гарантии возвращаемого буфера в C ++ 03 являются супер-набором.data()
, вы всегда можете безопасно его использовать.c_str()
, но люди иногда этого не делают, потому что:.data()
сообщает другим программистам, читающим исходный код, что данные не являются ASCIIZ (скорее, вы используете строку для хранения блока данных (который иногда даже не является действительно текстовым)), или что вы передаете его другая функция, которая обрабатывает его как блок «двоичных» данных. Это может быть критически важным для обеспечения того, чтобы изменения кода других программистов продолжали правильно обрабатывать данные.string
реализации потребуется дополнительное выделение памяти и / или копирование данных для подготовки буфера с NUL-ограничениемВ качестве еще одной подсказки, если для параметров функции требуется (
const
),char*
но они не настаивают на полученииx.size()
, функция, вероятно, нуждается в вводе ASCIIZ, так.c_str()
что это хороший выбор (функция должна знать, где текст заканчивается каким-то образом, так что если это не так В качестве отдельного параметра это может быть только соглашение, такое как префикс длины или часовой или некоторая фиксированная ожидаемая длина).Как сделать указатель на символ действительным даже после того, как
x
покидает область видимости или изменяется дальшеВам нужно будет скопировать содержимое в
string
x
новую область памяти снаружиx
. Этот внешний буфер может находиться во многих местах, например в другойstring
переменной или переменной массива символов, он может иметь или не иметь другое время жизни, отличное от того,x
что находится в другой области видимости (например, пространство имен, глобальное, статическое, куча, общая память, файл отображения памяти) ,Чтобы скопировать текст из
std::string x
в отдельный массив символов:Другие причины, чтобы хотеть
char*
илиconst char*
порожденный изstring
Итак, выше вы видели, как получить (
const
)char*
и как сделать копию текста независимой от оригиналаstring
, но что вы можете с этим сделать ? Случайная выборка примеров ...string
тексту C ++ , как вprintf("x is '%s'", x.c_str());
x
текст в буфер, указанный вызывающей стороной вашей функции (напримерstrncpy(callers_buffer, callers_buffer_size, x.c_str())
), или в энергозависимую память, используемую для ввода-вывода устройства (напримерfor (const char* p = x.c_str(); *p; ++p) *p_device = *p;
)x
текст в массив символов, уже содержащий некоторый текст ASCIIZ (напримерstrcat(other_buffer, x.c_str())
) - будьте осторожны, чтобы не переполнить буфер (во многих ситуациях вам может понадобиться использоватьstrncat
)const char*
илиchar*
функцию (возможно, по историческим причинам - клиент использует ваш существующий API - или для совместимости с C вы не хотите возвращать astd::string
, но действительно хотите скопировать своиstring
данные куда-нибудь для вызывающей стороны)string
переменная, на которую указывает этот указатель, вышла из области видимостиstd::string
реализаций (например, STLport и compiler-native), могут передавать данные как ASCIIZ, чтобы избежать конфликтовисточник
Используйте
.c_str()
метод дляconst char *
.Вы можете использовать
&mystring[0]
для полученияchar *
указателя, но есть несколько хитростей: вы не обязательно получите строку с нулевым символом в конце и вы не сможете изменить размер строки. Вы должны быть особенно осторожны, чтобы не добавлять символы после конца строки, иначе вы получите переполнение буфера (и возможное падение).Не было никакой гарантии, что все символы будут частью одного и того же непрерывного буфера до C ++ 11, но на практике все известные реализации
std::string
работали так или иначе; см. «& s [0]» указывает на смежные символы в std :: string? ,Обратите внимание, что многие
string
функции-члены перераспределяют внутренний буфер и делают недействительными любые указатели, которые вы могли сохранить. Лучше всего использовать их сразу, а затем отказаться.источник
C ++ 17
C ++ 17 (следующий стандарт) изменяет краткий обзор шаблона,
basic_string
добавляя неконстантную перегрузкуdata()
:CharT const *
отstd::basic_string<CharT>
CharT *
отstd::basic_string<CharT>
C ++ 11
CharT const *
отstd::basic_string<CharT>
CharT *
отstd::basic_string<CharT>
Начиная с C ++ 11, стандарт гласит:
Есть несколько возможных способов получить неконстантный символьный указатель.
1. Используйте непрерывное хранилище C ++ 11
профессионал
Cons
'\0'
не должен быть изменен / не обязательно является частью неконстантной памяти.2. Используйте
std::vector<CharT>
профессионал
Cons
3. Используйте,
std::array<CharT, N>
еслиN
это постоянная времени компиляции (и достаточно мала)профессионал
Cons
4. Необработанное выделение памяти с автоматическим удалением памяти
профессионал
Cons
5. Необработанное выделение памяти с ручной обработкой
профессионал
Против
источник
Я работаю с API с большим количеством функций, получаемых в качестве входных данных
char*
.Я создал небольшой класс для решения этой проблемы, я реализовал идиому RAII.
И вы можете использовать его как:
Я назвал класс,
DeepString
потому что он создает глубокую и уникальную копию (DeepString
не копируемую) существующей строки.источник
c_str()
используетсяstd
как «C-string», а не «const string» иstr()
всегда возвращает astd::basic_string
, а неchar*
(напримерstd::stringstream::str()
)источник
Просто посмотрите на это:
Тем не менее, обратите внимание, что это вернет
const char *
.Для
char *
, используйте,strcpy
чтобы скопировать его в другойchar
массив.источник
Попробуй это
источник