有没有办法获取 std:string 的缓冲区

发布于 2024-12-11 04:17:30 字数 262 浏览 0 评论 0原文

有没有办法获取 std::string 的“原始”缓冲区?
我正在考虑类似于 CString::GetBuffer() 的东西。例如,对于 CString 我会这样做:

CString myPath;  
::GetCurrentDirectory(MAX_PATH+1, myPath.GetBuffer(MAX_PATH));  
myPath.ReleaseBuffer();  

那么,std::string 有类似的东西吗?

Is there a way to get the "raw" buffer o a std::string?
I'm thinking of something similar to CString::GetBuffer(). For example, with CString I would do:

CString myPath;  
::GetCurrentDirectory(MAX_PATH+1, myPath.GetBuffer(MAX_PATH));  
myPath.ReleaseBuffer();  

So, does std::string have something similar?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

离旧人 2024-12-18 04:17:30

虽然有点不正统,但使用 std::string 作为线性内存缓冲区是完全有效的,唯一需要注意的是,直到 C++11 之前,标准才支持它。

std::string s;
char* s_ptr = &s[0]; // get at the buffer

引用草本萨特,

我所知道的每个 std::string 实现实际上都是连续的并且以 null 终止其缓冲区。所以,虽然还没有正式
保证,在实践中你可能可以通过调用 &str[0]
获取指向连续且以 null 结尾的字符串的指针。 (但是为了
为了安全起见,您仍然应该使用 str.c_str()。)

“可能” 是这里的关键。因此,虽然这不是保证,但您应该能够依赖 std::string 是线性内存缓冲区的原则,并且您应该在测试套件中断言有关此的事实,只是为了确保。

您始终可以构建自己的缓冲区类,但是当您想要购买时,这就是 STL 所提供的。

While a bit unorthodox, it's perfectly valid to use std::string as a linear memory buffer, the only caveat is that it isn't supported by the standard until C++11 that is.

std::string s;
char* s_ptr = &s[0]; // get at the buffer

To quote Herb Sutter,

Every std::string implementation I know of is in fact contiguous and null-terminates its buffer. So, although it isn’t formally
guaranteed, in practice you can probably get away with calling &str[0]
to get a pointer to a contiguous and null-terminated string. (But to
be safe, you should still use str.c_str().)

"Probably" is key here. So, while it's not a guarantee, you should be able to rely on the principle that std::string is a linear memory buffer and you should assert facts about this in your test suite, just to be sure.

You can always build your own buffer class but when you're looking to buy, this is what the STL has to offer.

小清晰的声音 2024-12-18 04:17:30

如果您想要一个真正的缓冲区,请使用 std::vector

#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 示例

Use std::vector<char> if you want a real buffer.

#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());
}

Example on Ideone.

新一帅帅 2024-12-18 04:17:30

不方便携带,不。该标准不保证 std::string 在内存中具有唯一的线性表示(并且使用旧的 C++03 标准,甚至允许像绳索这样的数据结构),因此 API 确实不让您访问它。它们必须能够将其内部表示更改为该表示(在 C++03 中)或允许访问其线性表示(如果有的话,这是在 C++11 中强制执行的),但仅限于读取。您可以使用 data() 和/或 c_str() 访问它。因此,该接口仍然支持写时复制。

使用通过指针访问来修改数组的 C-API 时,通常建议使用 std::vector,它保证具有恰好用于此目的的线性内存表示。

总而言之:如果您想以可移植的方式执行此操作,并且希望字符串以 std::string 结尾,则别无选择,只能将结果复制到字符串中。

Not portably, no. The standard does not guarantee that std::strings have an exclusive linear representation in memory (and with the old C++03 standard, even data-structures like ropes are permitted), so the API does not give you access to it. They must be able to change their internal representation to that (in C++03) or give access to their linear representation (if they have one, which is enforced in C++11), but only for reading. You can access this using data() and/or c_str(). Because of that, the interface still supports copy-on-write.

The usual recommendation for working with C-APIs that modify arrays by accessing through pointers is to use an std::vector, which is guaranteed to have a linear memory-representation exactly for this purpose.

To sum this up: if you want to do this portably and if you want your string to end up in an std::string, you have no choice but to copy the result into the string.

慢慢从新开始 2024-12-18 04:17:30

根据这篇 MSDN 文章,我认为这是直接使用 std::wstring 执行操作的最佳方法。第二好的是 std::unique_ptr,第三好的是使用 std::vector。请随意阅读这篇文章并得出您自己的结论。

// 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);

According to this MSDN article, I think this is the best approach for what you want to do using std::wstring directly. Second best is std::unique_ptr<wchar_t[]> and third best is using std::vector<wchar_t>. Feel free to read the article and draw you own conclusions.

// 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);
遗忘曾经 2024-12-18 04:17:30

它有 c_str,在我知道的所有 C++ 实现上,它返回底层缓冲区(但作为 const char *,所以你不能修改它)。

It has c_str, which on all C++ implementations that I know returns the underlying buffer (but as a const char *, so you can't modify it).

殊姿 2024-12-18 04:17:30
 std::string str("Hello world");
 LPCSTR sz = str.c_str();

请记住,当 str 被重新分配或超出范围时,sz 将失效。您可以执行类似以下操作来与字符串解耦:

 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);
 std::string str("Hello world");
 LPCSTR sz = str.c_str();

Keep in mind that sz will be invalidated when str is reallocated or goes out of scope. You could do something like this to decouple from the string:

 std::vector<char> buf(str.begin(), str.end()); // not null terminated
 buf.push_back(0); // null terminated

Or, in oldfashioned C style (note that this will not allow strings with embedded null-characters):

 #include <cstring>

 char* sz = strdup(str.c_str());

 // ... use sz

 free(sz);
就是爱搞怪 2024-12-18 04:17:30

我认为你这样做会被性传播疾病崇拜的纯粹主义者所皱眉。无论如何,如果您想要动态字符串类型可以轻松传递给低级 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 和其他基本类型。

I think you will be frowned upon by the purists of STD cult for doing this. In any case, its much better to not relay on bloated and generic standard library if you want dynamic string type that can be easily passed to low level API functions that will modify its buffer and size at the same time, without any conversions, than you will have to implement it! Its actually very challenging and interesting task to do. For example in my custom txt type I overload this operators:

ui64 operator~() const; // Size operator
uli32 * operator*();    // Size modification operator
ui64 operator!() const; // True Size Operator
txt& operator--();      // Trimm operator

And also this casts:

operator const char *() const;
operator char *();

And as such, i can pass txt type to low level API functions directly, without even calling any .c_str(). I can then also pass the API function it's true size (i.e. size of buffer) and also pointer to internal size variable (operator*()), so that API function can update amount of characters written, thus giving valid string without the need to call stringlength at all!

I tried to mimic basic types with this txt, so it has no public functions at all, all public interface is only via operators. This way my txt fits perfectly with ints and other fundamental types.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文