gpt4 book ai didi

c++ - std::vector 移动/重新分配内部 wstring.data() 合法吗?

转载 作者:太空狗 更新时间:2023-10-29 20:08:10 25 4
gpt4 key购买 nike

摘录如下:

...
std::vector<std::wstring> vecWstr;

vecWstr.emplace_back(L"1");
wchar_t* data1 = vecWstr[0].data(); //<-This pointer needed for future use.

vecWstr.emplace_back(L"2");
wchar_t* data2 = vecWstr[0].data();
if (data1 != data2)
MessageBox(L"Error, not equal.", L"Compare");

MessageBox总会出现。
所以,我在这里比较两个 wstring .emplace() 之前和之后的缓冲区.在我看来,它们必须相等。

这里主要关心的是:为什么vector移动/重新分配 1st innner std::wstring放置一秒后的元素?
这个问题是在对奇怪的程序行为进行调查后出现的。
如果我保存vecWstr[0].data()缓冲区指针之前.emplace()然后缓冲区指针变得过时并且程序行为不当。
最大的问题是有很多 std::vector<std::wstring>在一个程序中,但它们似乎都按预期工作,到目前为止只有一个像上面显示的那样。
这一切都在 MSVS 16.1.5

问题是:
谁在这里?可以std::vector更改/移动其 std::wstring 的内部缓冲区有没有元素?

最佳答案

在 C++ STL 中,有一种叫做指针失效的东西。这意味着,当您获得容器中某个元素的指针时,稍后您修改了容器,修改后您的指针可能不再有效。

指针失效的规则由标准定义,并且在容器与容器、操作与操作之间有所不同。

在您的例子中,您有一个 std::vector。如果您 emplace_back 并且 vector 需要更大的容量来添加元素,则指向 vector 元素的引用/指针/迭代器将不再有效。在这种情况下, vector 会在内存中分配另一个更大的空间并将其所有元素移动到那里。

但是等等!

您正在直接从字符串中获取 data() 指针!为什么这个指针也失效了? wstring 不应该是一个只包含指向某个堆缓冲区的指针的轻量级结构吗?

嗯,这就是 SSO(小字符串优化)的神奇之处。如果您的字符串足够小,wstring 只会将其缓冲区存储在数据结构本身中(而不是存储指向缓冲区的指针)。在这种情况下,当您移动它时,指针当然会失效。

您的字符串很小(1 个宽字符),因此它满足 SSO 的条件。如果你使用更长的:

std::vector<std::wstring> vecWstr;

vecWstr.emplace_back(L"asdfghjkl");
wchar_t* data1 = vecWstr[0].data(); //<-This pointer needed for future use.

vecWstr.emplace_back(L"qwertyuiop");
wchar_t* data2 = vecWstr[0].data();
if (data1 != data2)
MessageBox(0, L"Error, not equal.", L"Compare", 0);
return 0;

消息框可能不会弹出。

但是您无法控制运行时字符串的长度,并且您不知道编译器将如何实现 SSO,所以不要这样编码!

相反,您可以使用reserve 方法(正如songyuanyao 所建议的那样),或者使用其他在添加元素时不会使指针无效的容器。请引用std::liststd::deque .阅读有关它们的指针/引用/迭代器失效的部分。


关于c++ - std::vector<std::wstring> 移动/重新分配内部 wstring.data() 合法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56896539/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com