Есть ли способ получить std: string buffer
Есть ли способ получить "необработанный" буфер o std::string?
Я думаю о чем-то подобном CString::GetBuffer()
. Например, с CString я бы сделал:
CString myPath;
::GetCurrentDirectory(MAX_PATH+1, myPath.GetBuffer(MAX_PATH));
myPath.ReleaseBuffer();
Итак, имеет ли std::string что-то подобное?
Ответы
Ответ 1
Используйте std::vector<char>
, если вы хотите иметь реальный буфер.
#include <vector>
#include <string>
int main(){
std::vector<char> buff(MAX_PATH+1);
::GetCurrentDirectory(MAX_PATH+1, &buff[0]);
std::string path(buff.begin(), buff.end());
}
Пример в Ideone.
Ответ 2
В то время как немного неортодоксально, вполне допустимо использовать std::string
в качестве буфера линейной памяти, единственное предостережение в том, что оно не поддерживается стандартом до тех пор, пока не будет С++ 11.
std::string s;
char* s_ptr = &s[0]; // get at the buffer
Чтобы процитировать Herb Sutter,
Каждая реализация std::string, о которой я знаю, на самом деле смежна и null-завершает свой буфер. Итак, хотя это формально гарантировано, на практике вы, вероятно, можете уйти с вызовом & str [0] для получения указателя на непрерывную и нулевую строку. (Но быть безопасным, вы все равно должны использовать str.c_str().)
Вероятно, здесь ключ. Поэтому, хотя это не гарантия, вы должны полагаться на принцип, что std::string
- это буфер с линейной памятью, и вы должны утверждать факты об этом в своем тестовом наборе, чтобы быть уверенным.
Вы всегда можете создать свой собственный класс буферов, но когда вы хотите купить, это то, что может предложить STL.
Ответ 3
Не переносимо, нет. Стандарт не гарантирует, что std::string
имеет эксклюзивное линейное представление в памяти (и со старым стандартом С++ 03, даже такие структуры данных, как канаты, разрешены), поэтому API не дает вам доступа к нему. Они должны иметь возможность изменить свое внутреннее представление на это (в С++ 03) или предоставить доступ к их линейному представлению (если они есть один, который применяется на С++ 11), но только для чтения. Вы можете получить доступ к этому с помощью data()
и/или c_str()
. Из-за этого интерфейс по-прежнему поддерживает copy-on-write.
Обычная рекомендация по работе с C-API, которая модифицирует массивы путем доступа через указатели, - это использовать std::vector
, которая, как гарантируется, имеет линейную память-представление именно для этой цели.
Подводя итог этому: если вы хотите сделать это переносимо, и если вы хотите, чтобы ваша строка закончилась в std::string
, у вас нет выбора, кроме как скопировать результат в строку.
Ответ 4
Он имеет c_str
, который во всех реализациях С++, которые я знаю, возвращает базовый буфер (но как const char *
, поэтому вы не можете его изменять).
Ответ 5
std::string str("Hello world");
LPCSTR sz = str.c_str();
Имейте в виду, что sz будет признан недействительным, когда str перераспределяется или выходит за рамки. Вы можете сделать что-то вроде этого, чтобы отделить от строки:
std::vector<char> buf(str.begin(), str.end()); // not null terminated
buf.push_back(0); // null terminated
Или в старомодном стиле C (обратите внимание, что это не позволит строки со встроенными нулевыми символами):
#include <cstring>
char* sz = strdup(str.c_str());
// ... use sz
free(sz);
Ответ 6
В соответствии с этой статьей MSDN, я думаю, что это лучший подход к тому, что вы хотите сделать, используя std:: wstring непосредственно. Второй вариант - std::unique_ptr<wchar_t[]>
, а третий лучший - std::vector<wchar_t>
. Не стесняйтесь прочитать статью и сделать собственные выводы.
// Get the length of the text string
// (Note: +1 to consider the terminating NUL)
const int bufferLength = ::GetWindowTextLength(hWnd) + 1;
// Allocate string of proper size
std::wstring text;
text.resize(bufferLength);
// Get the text of the specified control
// Note that the address of the internal string buffer
// can be obtained with the &text[0] syntax
::GetWindowText(hWnd, &text[0], bufferLength);
// Resize down the string to avoid bogus double-NUL-terminated strings
text.resize(bufferLength - 1);