Как преобразовать std::string в const char* или char*?
Как я могу конвертировать std::string
к char*
или const char*
?
11 ответов
Если вы просто хотите пройти std::string
к функции, которая нуждается const char*
ты можешь использовать
std::string str;
const char * c = str.c_str();
Если вы хотите получить доступную для записи копию, например, char *
Вы можете сделать это с этим:
std::string str;
char * writable = new char[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 it
delete[] writable;
Изменить: Обратите внимание, что выше не является исключением исключений. Если что-нибудь между new
вызов и delete
перебрось вызов, утечка памяти, как ничего delete
для вас автоматически. Есть два непосредственных способа решить это.
повышение::scoped_array
boost::scoped_array
удалит память для вас после выхода из области видимости:
std::string str;
boost::scoped_array<char> writable(new char[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()
Дано сказать...
std::string x = "hello";
Получение `char *` или `const char*` из `строки`
Как получить указатель на символ, который действует в то время как x
остается в области и не изменяется в дальнейшем
C++11 упрощает вещи; следующие все дают доступ к одному и тому же внутреннему строковому буферу:
const char* p_c_str = x.c_str();
const char* p_data = x.data();
const char* 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
указатель от &x[0]
:
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()
но:- для не
const
x
это приводит кconst
char*
указатель; Вы можете перезаписать содержимое строки
- для не
- для пустых строк это имеет неопределенное поведение (21.3.4)
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
или резервирует дополнительную емкость, любые значения указателя, возвращенные заранее любым из вышеуказанных методов, становятся недействительными. Вы можете использовать эти методы снова, чтобы получить другой указатель. (Правила те же, что и для итераторов в string
с).
Смотрите также Как получить указатель на символ, действительный даже после x
покидает область видимости или изменяется ниже....
Итак, что лучше использовать?
С C++11 используйте .c_str()
для данных ASCIIZ, и .data()
для "двоичных" данных (объяснено ниже).
В C++ 03 используйте .c_str()
если не уверен, что .data()
адекватный, и предпочитаю .data()
над &x[0]
как это безопасно для пустых строк....
... попытаться понять программу достаточно, чтобы использовать data()
когда уместно, или вы, вероятно, будете делать другие ошибки...
Символ ASCII NUL '\0' гарантируется .c_str()
используется многими функциями в качестве дозорного значения, обозначающего конец релевантных и безопасных для доступа данных. Это относится как к С ++, так и к таким функциям, как скажем fstream::fstream(const char* filename, ...)
и разделяемые с C функции, такие как strchr()
, а также printf()
,
Учитывая C++ 03 .c_str()
гарантии возвращаемого буфера - это супер-набор .data()
х, вы всегда можете безопасно использовать .c_str()
, но люди иногда не потому, что:
- с помощью
.data()
сообщает другим программистам, читающим исходный код, что данные не являются ASCIIZ (скорее, вы используете строку для хранения блока данных (который иногда даже не является действительно текстовым)), или что вы передаете его другому функция, которая обрабатывает его как блок "двоичных" данных. Это может быть критически важным для обеспечения того, чтобы изменения кода других программистов продолжали обрабатывать данные должным образом. - Только C++ 03: есть небольшой шанс, что ваш
string
Реализация должна будет сделать дополнительное выделение памяти и / или копирование данных, чтобы подготовить NUL-завершенный буфер
В качестве дополнительной подсказки, если для параметров функции требуется (const
) char*
но не настаивайте на получении x.size()
функция, вероятно, нуждается во входе ASCIIZ, поэтому .c_str()
это хороший выбор (функция должна знать, где текст каким-то образом заканчивается, поэтому, если это не отдельный параметр, это может быть только соглашение, такое как префикс длины или часовой или какая-то фиксированная ожидаемая длина).
Как получить указатель на символ действительным даже после x
покидает область видимости или изменяется далее
Вам нужно будет скопировать содержимое string
x
в новую область памяти снаружи 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) LENGTH
char* 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 SAFETY
char* y = new char[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 SAFETY
char* y = strdup(x.c_str());
// use y...
free(y);
Другие причины хотеть char*
или же const char*
генерируется из string
Итак, выше вы видели, как получить (const
) char*
и как сделать копию текста независимой от оригинала string
, но что вы можете с этим сделать? Случайная выборка примеров...
- дать доступ к коду на C++
string
текст, как в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 вы не хотите возвращатьstd::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* data() noexcept;
Возвращает: указатель p такой, что p + i == & оператор для каждого i в [0,size()].
CharT const *
от std::basic_string<CharT>
std::string const cstr = { "..." };
char const * 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()
,
const_reference operator[](size_type pos) const;
reference operator[](size_type pos);
Возвращает:
*(begin() + pos)
еслиpos < size()
в противном случае ссылка на объект типаCharT
со значениемCharT()
; указанное значение не должно изменяться.
const charT* c_str() const noexcept;
const charT* data() const noexcept;
Возвращает: указатель p такой, что
p + i == &operator[](i)
для каждогоi
в[0,size()]
,
Есть несколько возможных способов получить неконстантный символьный указатель.
1. Используйте непрерывное хранилище C++11
std::string foo{"text"};
auto p = &*foo.begin();
профессионал
- Простой и короткий
- Быстро (только метод без копирования)
Cons
- окончательный
'\0'
не должен быть изменен / не обязательно является частью неконстантной памяти.
2. Используйте std::vector<CharT>
std::string foo{"text"};
std::vector<char> fcv(foo.data(), foo.data()+foo.size()+1u);
auto p = fcv.data();
профессионал
- просто
- Автоматическая обработка памяти
- динамический
Cons
- Требуется копия строки
3. Используйте std::array<CharT, N>
если N
является постоянной времени компиляции (и достаточно маленькой)
std::string foo{"text"};
std::array<char, 5u> fca;
std::copy(foo.data(), foo.data()+foo.size()+1u, fca.begin());
профессионал
- просто
- Обработка стековой памяти
Cons
- статический
- Требуется копия строки
4. Необработанное выделение памяти с автоматическим удалением памяти
std::string foo{ "text" };
auto p = std::make_unique<char[]>(foo.size()+1u);
std::copy(foo.data(), foo.data() + foo.size() + 1u, &p[0]);
профессионал
- Маленький объем памяти
- Автоматическое удаление
- просто
Cons
- Требуется копия строки
- Статический (динамическое использование требует намного больше кода)
- Меньше возможностей, чем вектор или массив
5. Необработанное выделение памяти с ручной обработкой
std::string foo{ "text" };
char * p = nullptr;
try
{
p = new char[foo.size() + 1u];
std::copy(foo.data(), foo.data() + foo.size() + 1u, p);
// handle stuff with p
delete[] p;
}
catch (...)
{
if (p) { delete[] p; }
throw;
}
профессионал
- Максимальный "контроль"
Против
- Требуется копия строки
- Максимальная ответственность / восприимчивость к ошибкам
- Сложный
Просто посмотрите на это:
string str1("stackru");
const char * str2 = str1.c_str();
Тем не менее, обратите внимание, что это вернет const char *
.Для char *
использовать strcpy
скопировать его в другой char
массив.
Я работаю с API с большим количеством функций, получить как вход char*
,
Я создал небольшой класс для решения этой проблемы, я реализовал идиому RAII.
class DeepString
{
DeepString(const DeepString& other);
DeepString& operator=(const DeepString& other);
char* internal_;
public:
explicit DeepString( const string& toCopy):
internal_(new char[toCopy.size()+1])
{
strcpy(internal_,toCopy.c_str());
}
~DeepString() { delete[] internal_; }
char* str() const { return internal_; }
const char* c_str() const { return internal_; }
};
И вы можете использовать его как:
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
не копируется) существующей строки.
char* result = strcpy((char*)malloc(str.length()+1), str.c_str());
Преобразование из строки std c ++ в строку стиля C теперь действительно просто.
Для этого у нас есть функция, которая легко конвертирует строку std в строку стиля C. ссылка
string::copy
параметры функций последовательно
- указатель строки char
- размер строки, сколько символов будет скопировано
- позиция, с которой будет начинаться копирование символа
Еще одна важная вещь,
Эта функция не добавляет нулевой символ в конце операции. Значит, нам нужно поставить вручную.
Экзамен по коду находится ниже -
// char string
char chText[20];
// c++ string
string text = "I am a Programmer";
// conversion from c++ string to char string
// this function does not append a null character at the end of operation
text.copy(chText, text.size(), 0);
// we need to put it manually
chText[text.size()] = '\0';
// below statement prints "I am a Programmer"
cout << chText << endl;
скажем, строка str ="stack";
1)преобразование строки в char*
char* s_rw=&str[0];
Вышеупомянутый char* (т.е. s_rw) доступен для чтения и записи и указывает на базовый адрес строки, которую необходимо преобразовать в char*
2) Преобразование строки в const char*
const char* s_r=&str[0];
Вышеупомянутый const char* (т.е. s_r) доступен для чтения, но не для записи и указывает на базовый адрес строки.
Это особенно полезно при передаче базового буфера вызовов a to C, которые ожидают и записывают в буфер. Таким образом, вы получаете лучшее из обоих миров!: тонкости C++ и удобство его использования непосредственно с библиотеками C, которые вы вызываете из C++.
Как использовать современный C++ как C-стиль для чтения/записи или только для чтения с нулем в конце
Как я могу преобразовать a в a или a ?
Несмотря на то, что это действительно старый и получивший большое количество голосов ответ, информация, которую я собираюсь рассказать, еще недостаточно хорошо освещена, если вообще освещена, так что это необходимое дополнение, в частности , часть о необходимости предварительного выделения базовая C-строка с помощью метода, если вы хотите использовать ее в качестве доступного для записи буфера.
Для всех приведенных ниже применений требуется C++11 или более поздняя версия, за исключениемcall, для которого требуется C++17 или более поздняя версия.
Чтобы запустить и протестировать все приведенные ниже примеры кода и многое другое, просмотрите и запустите мой файл в моем репозитории eRCaGuy_hello_world .
1. Используйте как доступный для чтения/записи
Чтобы использовать C++ в качестве доступного для записи буфера в стиле C , вы ДОЛЖНЫ сначала предварительно выделить внутренний буфер строки, чтобы изменить его
.size()
используя
.resize()
. Обратите внимание, что использование
.reserve()
увеличивать только
.capacity()
НЕ достаточно! Вики - правильно указывает:
Если
pos > size()
, поведение не определено.
Метод - это то, что изменяет размер, а
неreserve()
метод, который изменяет только
capacity()
.
Бывший:
#include <cstring> // `strcpy()`
#include <iostream>
#include <string>
constexpr size_t BUFFER_SIZE = 100;
std::string str;
str.resize(BUFFER_SIZE); // pre-allocate the underlying buffer
// check the size
std::cout << "str.size() = " << str.size() << "\n";
Для всех приведенных ниже примеров предположим, что у вас есть следующие C-строки:
constexpr char cstr1[] = "abcde ";
constexpr char cstr2[] = "fghijk";
После того, как вы предварительно выделили базовый буфер, который достаточно велик с
resize()
, вы можете получить доступ к базовому буферу как минимум тремя способами:
- Техника 1 [лучший вариант при использовании C++11]: индексация массива с использованием для получения символа с последующим получением его адреса с помощью
&
.Бывший:char* c_str; c_str = &str[0]; c_str = &str[5]; // etc. // Write these 2 C-strings into a `std::string`'s underlying buffer strcpy(&str[0], cstr1); strcpy(&str[sizeof(cstr1) - 1], cstr2); // `- 1` to overwrite the first // null terminator // print the string std::cout << str << "\n"; // output: `abcde fghijk`
*pstr
прежде чем вы сможете индексировать его как массив сoperator[]
в качестве&(*pstr)[0]
, поэтому приведенный выше синтаксис становится немного более неудобным. Вот полный пример:std::string str2; std::string* pstr = &str2; pstr->resize(BUFFER_SIZE); c_str = &(*pstr)[0]; // <=== dereference the ptr 1st before indexing into it // Or, to make the order of precedence // (https://en.cppreference.com/w/cpp/language/operator_precedence) really // obvious, you can optionally add extra parenthesis like this: c_str = &((*pstr)[0]);
- Способ 2[лучший вариант при использовании C++17]: используйте метод для прямого получения файла .Бывший:
char* c_str; c_str = str.data(); c_str = str.data() + 5; // etc. // Write these 2 C-strings into the `std::string`'s underlying buffer strcpy(str.data(), cstr1); strcpy(str.data() + (sizeof(cstr1) - 1), cstr2); // `- 1` to overwrite the // first null terminator // print the string std::cout << str << "\n"; // output: `abcde fghijk`
- Техника 3 [прекрасна в C++11, но неудобна]: используйте
.begin()
метод, чтобы получить итератор для первого символа, а затем использовать итераторoperator*()
метод разыменования для получения значения итератораvalue_type
, а затем возьмите его адрес, чтобы получитьchar*
.Бывший:char* c_str; c_str = &(*str.begin()); c_str = &(*str.begin()) + 5; // etc. // Write these 2 C-strings into the `std::string`'s underlying buffer strcpy(&(*str.begin()), cstr1); strcpy(&(*str.begin()) + (sizeof(cstr1) - 1), cstr2); // `- 1` to overwrite // the first null // terminator // print the string std::cout << str << "\n"; // output: `abcde fghijk`
Важно помнить, что когда вы звоните
str.resize(100)
, он резервирует не менее 100 байтов для базовой строки, устанавливает
size()
строки в , и инициализирует все эти символы в
char()
--AKA: значение инициализации по умолчанию для
char
( ), который является двоичным нулевым нулевым терминатором,
'\0'
. Поэтому всякий раз, когда вы звоните
str.size()
он вернется
100
даже если строка просто имеет
"hello"
за ним следуют 95 завершающих нулей или нулей. Чтобы получить длину или количество ненулевых терминаторов в строке, вам придется прибегнуть к функции C
strlen()
, как это:
std::cout << strlen(str.c_str()) << "\n"; // prints `12` in the examples above
// instead of:
std::cout << str.size() << "\n"; // prints `100` in the examples above
2. Доступ к a как доступный только для чтения, завершающийся нулем.
Чтобы получить читаемый нуль-завершающийся
const char*
из
std::string
, использоватьметод. Он возвращает строку в стиле C, которая гарантированно завершается нулем . Обратите внимание, чтометод - это НЕ одно и то же, так как НЕ гарантируется, что он завершится нулем!
Пример:
std::string str = "hello world";
printf("%s\n", str.c_str());
использованная литература
(вопросы о переполнении стека)
- Как преобразовать std::string в const char* или char*:Как преобразовать std::string в const char* или char*
- Непосредственная запись в буфер char* из std::string:Непосредственная запись в буфер char* из std::string
- Есть ли способ получить буфер std:string:Есть ли способ получить буфер std:string
(мой контент)
- [мой тестовый код] string__use_std_string_as_a_c_str_buffer.cppstring__use_std_string_as_a_c_str_buffer.cpp
- [мой вопрос] См. Раздел «Смежные» внизу моего вопроса здесь:см. мой вопрос здесьЧто такое вызов `char()` как функции в C++?
- *****+ [мои комментарии о предварительном выделении буфера в std::string]:Напрямую писать в char* буфер std::string
- *****+ [мой комментарий о том, как предварительно выделить память в std::string для использования в качестве буфера char*]Есть ли способ получить буфер std:string
(из вики сообщества cppreference.com)
https://en.cppreference.com/w/cpp/string/basic_string :
Элементы base_string хранятся непрерывно, то есть для basic_string s, &*(s.begin() + n) == &*s.begin() + n для любого n в [0, s.size()) или, что то же самое, указатель на s[0] может быть передан функциям, которые ожидают указатель на первый элемент массива CharT[] с завершающим нулем (начиная с C++11).
-
Возвращает ссылку на символ в указанном месте поз. Проверка границ не выполняется. Если pos > size(), поведение не определено.
https://en.cppreference.com/w/cpp/string/basic_string/resize
https://en.cppreference.com/w/cpp/string/basic_string/reserve
char* data()
https://en.cppreference.com/w/cpp/string/basic_string/data.data()
.c_str()
https://en.cppreference.com/w/cpp/string/basic_string/c_str
Попробуй это
std::string s(reinterpret_cast<const char *>(Data), Size);