有没有一种方法可以获取std::string的“原始”缓冲区?
我考虑的是类似于的东西。举个例子,对于CString,我会这样做:
CString myPath;
::GetCurrentDirectory(MAX_PATH+1, myPath.GetBuffer(MAX_PATH));
myPath.ReleaseBuffer();
那么,std::string有类似的东西吗?
虽然有点不寻常,但将std::string
用作线性内存缓冲区是完全有效的,唯一需要注意的是在C++11之前的标准中并不支持它。
std::string s;
char* s_ptr = &s[0]; // get at the buffer
引用Herb Sutter的话:
在我所知的每个
std::string
实现中,它实际上都是连续的并以null结尾的。因此,虽然它在形式上不能保证,但在实践中您可能可以通过调用&str[0]
来获取指向连续和以null结尾的字符串的指针。(但为了安全起见,您仍应使用str.c_str()
。)
“可能”在这里是关键。因此,虽然这不是一项保证,但您应该能够依赖于std::string
是线性内存缓冲区的原则,并且应该在测试套件中断言这些事实,以确保安全。
您总是可以构建自己的缓冲类,但当您想要购买时,这就是STL提供的东西。
char *
一样向这个std::string
缓冲区中写入内容,你必须使用s.resize(BUFFER_SIZE)
预先分配缓冲区的大小,否则写入该缓冲区是未定义的行为。s.reserve(BUFFER_SIZE)
不能满足需求。参见:https://en.cppreference.com/w/cpp/string/basic_string/operator_at:“如果`pos > size(),行为是未定义的。”因此,你可以使用
s.resize()强制分配值为空终止字符的缓冲区,直到达到指定的大小。然后,你可以像正常的
char *`一样在其大小范围内写入该缓冲区。 - Gabriel Staples如果你想要一个真正的缓冲区,请使用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());
}
std::unique_ptr<char[]>
或堆栈分配。如果不需要初始化缓冲区,请勿浪费CPU资源。 - John Leidegrenstd::vector<char>
不会像 memset(..., 0, sizeof ...)
那样聪明地执行任何操作,尽管后者速度更快,但前者会对每个元素进行适当的初始化。 - John Leidegren根据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);
std::string str("Hello world");
LPCSTR sz = str.c_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);
LPCSTR
和其他Windows-ism的帖子。 - Fred Foo我认为纯粹主义者会对你这样做表示不满。无论如何,如果你想要一个动态字符串类型,可以轻松地传递给低级API函数,并且在同一时间修改其缓冲区和大小,而不需要进行任何转换,那么最好不要依赖臃肿和通用的标准库,而是自己实现它!实际上,这是一个非常具有挑战性和有趣的任务。例如,在我的自定义txt
类型中,我重载了这些运算符:
ui64 operator~() const; // Size operator
uli32 * operator*(); // Size modification operator
ui64 operator!() const; // True Size Operator
txt& operator--(); // Trimm operator
还有这个强制转换:
operator const char *() const;
operator char *();
因此,我可以直接将txt
类型传递给低级API函数,甚至不需要调用任何.c_str()
。然后,我还可以传递API函数的真实大小(即缓冲区的大小)和指向内部大小变量的指针(operator*()
),以便API函数可以更新写入的字符数,从而无需调用stringlength
就能得到有效字符串!
我试图通过这个txt
来模拟基本类型,因此它根本没有公共函数,所有公共接口都是通过运算符进行的。这样,我的txt
与int
和其他基本类型完美匹配。
std::string
转换为const char*
或char*
。 - Gabriel Staples