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

2024-05-10

以下是摘录:

...
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移动/重新分配第一个内部std::wstring放置第二个元素后?
在对奇怪的程序行为进行调查后出现了这个问题。
如果我保存vecWstr[0].data()缓冲区指针before second .emplace()那么缓冲区指针就会过时并且程序行为不正确。
最大的问题是有很多std::vector<std::wstring>在一个程序中,但所有这些似乎都按预期工作,到目前为止只有一个如上所示。
这一切都在微软VS 16.1.5

问题是:
谁在这里?能std::vector更改/移动其内部缓冲区std::wstring元素与否?


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

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

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

可是等等!

你正在服用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 建议的那样),或使用其他在添加元素时不会使指针无效的容器。请参阅标准::列表 https://en.cppreference.com/w/cpp/container/list and std::双端队列 https://en.cppreference.com/w/cpp/container/deque。阅读有关指针/引用/迭代器失效的部分。


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

std::vector 移动/重新分配内部 wstring.data() 合法吗? 的相关文章

  • 添加 Nullable int 时保持 null?

    我想添加可为空的int 并保留null当所有值都是null 我想要这个结果 1 2 3 1 null 1 null null null O null 0 问题是 如果我将一个值与 null 相加 结果为 null int i1 1 int
  • json.net自定义jobject反序列化

    我正在尝试使用 JsonConvert DeserializeObject string 将字符串反序列化为可与动态一起使用的 jobject 来动态访问 json 文档 但是我想避免知道文档的大小写 以便我可以输入 dynamic doc
  • 将 new 与 decltype 一起使用

    T t T is an implementation detail t new T want to avoid naming T to allow for flexibility t new decltype t error cannot
  • 在 OnModelCreating 期间设置列名称

    Issue 我目前正在尝试通过设置的属性为我的表及其列添加前缀 我正在使用实体框架核心 我已经正确地为表名添加了前缀 但我似乎无法弄清楚列的前缀 我有一种感觉 我需要使用反射 我已经留下了我的 可能很糟糕的 反思尝试 有人有办法在实体中设置
  • C++ 长 switch 语句还是用地图查找?

    在我的 C 应用程序中 我有一些值充当代表其他值的代码 为了翻译代码 我一直在争论使用 switch 语句还是 stl 映射 开关看起来像这样 int code int value switch code case 1 value 10 b
  • 检测wlan是否关闭

    任何人都可以给我一个提示 如何在 Windows Phone 上以编程方式检测 C 8 1 应用程序 不是 8 0 是否启用 禁用 WLAN 我不想更改这些设置 只是需要知道 该解决方案是一个 Windows 8 1 通用应用程序 Wind
  • 从模板切换传递的类型

    在 C 中是否可以检查传递给模板函数的类型 例如 template
  • 为什么'enable_if'不能用于禁用这里声明

    include
  • 访问 ascx 文件中的母版页控件

    我有一个母版页文件 其中包含 2 个面板控件中的 2 个菜单 我还使用控件来检查用户是否登录并获取用户类型 根据我想要显示 隐藏面板的类型 控件本身不在母版页中引用 而是通过 CMS 系统动态引用 我想在用户控件中使用findcontrol
  • 使用查询表达式对 List 进行排序

    我在使用 Linq 订购这样的结构时遇到问题 public class Person public int ID get set public List
  • C# 编译器不会优化不必要的强制转换

    前几天 在写答案的时候这个问题 https stackoverflow com questions 2208315 why is any slower than contains在这里 关于溢出 我对 C 编译器感到有点惊讶 它没有按照我的
  • MFC:如何设置CEdit框的焦点?

    我正在开发我的第一个简单的 MFC 项目 但我正在努力解决一个问题 想要设置所有的焦点CEdit其中一个对话框中的框 我的想法是 当打开对话框时 焦点位于第一个编辑框上 然后使用 选项卡 在它们之间交换 我看到了方法SetFocus 但我无
  • 将接口转换为其具体实现对象,反之亦然?

    在 C 中 当我有一个接口和几个具体实现时 我可以将接口强制转换为具体类型 还是将具体类型强制转换为接口 这种情况下的规则是什么 Java 和 C 中都允许这两个方向 向下转型需要显式转型 如果对象类型不正确 可能会抛出异常 然而 向上转换
  • UI 函数在快速事件完成之前触发

    我有一个停靠在 Silverlight 应用程序中的 Web 浏览器框架 有时会在其上弹出全窗口 XAML Silverlight UI 元素 我已经或多或少修复了一个老问题 即 Web 框架的内容似乎与 Silverlight 内容不能很
  • 引用/指针失效到底是什么?

    我找不到任何定义指针 引用无效在标准中 我问这个问题是因为我刚刚发现 C 11 禁止字符串的写时复制 COW 据我了解 如果应用了 COW 那么p仍然是一个有效的指针并且r以下命令后的有效参考 std string s abc std st
  • Project Euler #8,我不明白我哪里出了问题[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我正在做项目欧拉第八题 https projecteuler net problem 8 其中我得到了这个大得离谱的数字 7316
  • 如何从 Rx Subscribe 回调异步函数?

    我想回调 Rx 订阅中的异步函数 例如 像那样 public class Consumer private readonly Service service new Service public ReplaySubject
  • 在 OpenGL 中渲染纹理 1 到 1

    所以我想做的是使用 OpenGL 和 C 将纹理渲染到平面上 作为显示图像的一种方式 但是我需要确保在渲染纹理时没有对纹理进行任何处理 抗锯齿 插值 平滑 模糊等 这是 OpenGL 处理渲染纹理的默认方式吗 或者是否需要设置一些标志才能禁
  • 如何将 SQL“LIKE”与 LINQ to Entities 结合使用?

    我有一个文本框 允许用户指定搜索字符串 包括通配符 例如 Joh Johnson mit ack on 在使用 LINQ to Entities 之前 我有一个存储过程 该存储过程将该字符串作为参数并执行以下操作 SELECT FROM T
  • 使用未分配的局部变量

    我遇到了一个错误 尽管声明了变量 failturetext 和 userName 错误仍然出现 谁能帮帮我吗 Use of Unassigned local variable FailureText Use of Unassigned lo

随机推荐