Есть ли способ получить 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);