std::launder 可用于将对象指针转换为其封闭数组指针吗?

2024-03-31

当前的标准草案(大概是 C++17)说[基本.化合物/4] http://eel.is/c++draft/basic.compound#4:

[ 注意:数组对象及其第一个元素不可进行指针互换,即使它们具有相同的地址。 ——《尾注》

所以指向对象的指针不能reinterpret_castd 获取其封闭的数组指针。

现在,有std::launder, [ptr.launder/1] http://eel.is/c++draft/ptr.launder#1:

template<class T> [[nodiscard]] constexpr T* launder(T* p) noexcept;

要求:p表示内存中一个字节的地址A。处于其生命周期内且类型与 T 类似的对象 X 位于地址 A 处。通过结果可访问的所有存储字节都可通过以下方式访问:p(见下文)。

和定义可达的 is in [ptr.launder/3] http://eel.is/c++draft/ptr.launder#3:

备注: 只要该函数的参数值可以在核心常量表达式中使用,就可以在核心常量表达式中使用该函数的调用。如果一个字节的存储空间位于 Y 所占用的存储空间内,则该字节可以通过指向对象 Y 的指针值来访问,该指针值是与 Y 可以进行指针互换的对象,或者是如果 Y 是数组元素,则直接封闭数组对象。如果 T 是函数类型或 cv void,则程序格式错误。

现在乍一看,似乎std::launder因为我强调的部分,所以可以用来进行上述转换。

But. If p指向数组的对象,数组的字节为可达的根据这个定义(即使p不可将指针相互转换为数组指针),就像清洗的结果一样。所以,这个定义似乎没有提到这个问题。

So, can std::launder用于将对象指针转换为其封闭数组指针?


这取决于封闭数组对象是否是一个完整的对象,如果不是,您是否可以通过指向该封闭数组对象的指针有效地访问更多字节(例如,因为它本身是一个数组元素,或者可以与更大的对象进行指针互转换) ,或与数组元素的对象进行指针互换)。 “可达”要求意味着您不能使用launder获取一个指针,该指针允许您访问比源指针值允许的更多字节,但存在未定义的行为。这确保了某些未知代码可能调用的可能性launder不影响编译器的转义分析。

我想一些例子会有所帮助。下面每个例子reinterpret_casts a int*指向 10 数组的第一个元素int变成一个int(*)[10]。由于它们不可进行指针互换,reinterpret_cast不改变指针值,你会得到一个int(*)[10]值为“指向第一个元素(无论数组是什么)的指针”。然后,每个示例尝试通过调用来获取指向整个数组的指针std::launder在强制转换指针上。

int x[10];
auto p = std::launder(reinterpret_cast<int(*)[10]>(&x[0])); 

还行吧;您可以访问的所有元素x通过源指针,以及结果launder不允许您访问任何其他内容。

int x2[2][10];
auto p2 = std::launder(reinterpret_cast<int(*)[10]>(&x2[0][0])); 

这是未定义的。您只能访问以下元素x2[0]通过源指针,但结果(这将是一个指向x2[0])将允许您访问 x2[1],但您无法通过源访问。

struct X { int a[10]; } x3, x4[2]; // assume no padding
auto p3 = std::launder(reinterpret_cast<int(*)[10]>(&x3.a[0])); // OK

还行吧。同样,您不能通过指针访问x3.a您还无法访问的任何字节。

auto p4 = std::launder(reinterpret_cast<int(*)[10]>(&x4[0].a[0])); 

这是(打算)未定义的。你本来可以到达x4[1]从结果来看,因为x4[0].a是指针可相互转换的x4[0],所以指向前者的指针可以是reinterpret_cast产生指向后者的指针,然后可以将其用于指针算术。看https://wg21.link/LWG2859 https://wg21.link/LWG2859.

struct Y { int a[10]; double y; } x5;
auto p3 = std::launder(reinterpret_cast<int(*)[10]>(&x5.a[0])); 

这又是未定义的,因为你本来可以达到x5.y从结果指针(通过reinterpret_cast to a Y*)但源指针不能用于访问它。

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

std::launder 可用于将对象指针转换为其封闭数组指针吗? 的相关文章

  • 属性对象什么时候创建?

    由于属性实际上只是附加到程序集的元数据 这是否意味着属性对象仅根据请求创建 例如当您调用 GetCustomAttributes 时 或者它们是在创建对象时创建的 或者 前两个的组合 在由于 CLR 的属性扫描而创建对象时创建 从 CLR
  • 嵌入式系统中的malloc [重复]

    这个问题在这里已经有答案了 我正在使用嵌入式系统 该应用程序在 AT91SAMxxxx 和 cortex m3 lpc17xxx 上运行 我正在研究动态内存分配 因为它会极大地改变应用程序的外观 并给我更多的力量 我认为我唯一真正的路线是为
  • FFMPEG Seeking 带来音频伪影

    我正在使用 ffmpeg 实现音频解码器 在读取音频甚至搜索已经可以工作时 我无法找到一种在搜索后清除缓冲区的方法 因此当应用程序在搜索后立即开始读取音频时 我没有任何工件 avcodec flush buffers似乎对内部缓冲区没有任何
  • 跨多个控件共享事件处理程序

    在我用 C 编写的 Windows 窗体应用程序中 我有一堆按钮 当用户的鼠标悬停在按钮上时 我希望按钮的边框发生变化 目前我有以下多个实例 每个按钮一个副本 private void btnStopServer MouseEnter ob
  • c 中的错误:声明隐藏了全局范围内的变量

    当我尝试编译以下代码时 我收到此错误消息 错误 声明隐藏了全局范围内的变量 无效迭代器 节点 根 我不明白我到底在哪里隐藏或隐藏了之前声明的全局变量 我怎样才能解决这个问题 typedef node typedef struct node
  • 为什么模板不能位于外部“C”块内?

    这是一个后续问题一个答案 https stackoverflow com questions 4866433 is it possible to typedef a pointer to extern c function type wit
  • 在 ASP.Net Core 2.0 中导出到 Excel

    我曾经使用下面的代码在 ASP NET MVC 中将数据导出到 Excel Response AppendHeader content disposition attachment filename ExportedHtml xls Res
  • A* 之间的差异 pA = 新 A;和 A* pA = 新 A();

    在 C 中 以下两个动态对象创建之间的确切区别是什么 A pA new A A pA new A 我做了一些测试 但似乎在这两种情况下 都调用了默认构造函数 并且仅调用了它 我正在寻找性能方面的任何差异 Thanks If A是 POD 类
  • 使用安全函数在 C 中将字符串添加到字符串

    我想将文件名复制到字符串并附加 cpt 但我无法使用安全函数 strcat s 来做到这一点 错误 字符串不是空终止的 我确实设置了 0 如何使用安全函数修复此问题 size strlen locatie size nieuw char m
  • 如何在 Team Foundation 上强制发表有意义的签入评论?

    我有一个开发团队有一个坏习惯 他们写道poor签入评论 当我们必须在团队基础上查看文件的历史记录时 这使得它成为一场噩梦 我已经启用了变更集评论政策 这样他们甚至可以在签到时留下评论 否则他们不会 我们就团队的工作质量进行了一些讨论 他们很
  • 初始化变量的不同方式

    在 C 中初始化变量有多种方法 int z 3 与 int 相同z 3 Is int z z 3 same as int z z 3 您可以使用 int z z 3 Or just int z 3 Or int z 3 Or int z i
  • 像“1$”这样的位置参数如何与 printf() 一起使用?

    By man I find printf d width num and printf 2 1 d width num 是等价的 但在我看来 第二种风格应该与以下相同 printf d num width 然而通过测试似乎man是对的 为什
  • 可空属性与可空局部变量

    我对以下行为感到困惑Nullable types class TestClass public int value 0 TestClass test new TestClass Now Nullable GetUnderlyingType
  • 将日期参数传递给对 MVC 操作的 ajax 调用的安全方法

    我有一个 MVC 操作 它的参数之一是DateTime如果我通过 17 07 2012 它会抛出一个异常 指出参数为空但不能有空值 但如果我通过01 07 2012它被解析为Jan 07 2012 我将日期传递给 ajax 调用DD MM
  • 如何构建印度尼西亚电话号码正则表达式

    这些是一些印度尼西亚的电话号码 08xxxxxxxxx 至少包含 11 个字符长度 08xxxxxxxxxxx 始终以 08 开头 我发现这个很有用 Regex regex new Regex 08 0 9 0 9 0 9 0 9 0 9
  • 如何在内存中存储分子?

    我想将分子存储在内存中 这些可以是简单的分子 Methane CH4 C H bond length 108 7 pm H H angle 109 degrees But also more complex molecules like p
  • ListDictionary 类是否有通用替代方案?

    我正在查看一些示例代码 其中他们使用了ListDictionary对象来存储少量数据 大约 5 10 个对象左右 但这个数字可能会随着时间的推移而改变 我使用此类的唯一问题是 与我所做的其他所有事情不同 它不是通用的 这意味着 如果我在这里
  • 如何在 C# 中播放在线资源中的 .mp3 文件?

    我的问题与此非常相似question https stackoverflow com questions 7556672 mp3 play from stream on c sharp 我有音乐网址 网址如http site com aud
  • 将 viewbag 从操作控制器传递到部分视图

    我有一个带有部分视图的 mvc 视图 控制器中有一个 ActionResult 方法 它将返回 PartialView 因此 我需要将 ViewBag 数据从 ActionResult 方法传递到 Partial View 这是我的控制器
  • 为什么 strtok 会导致分段错误?

    为什么下面的代码给出了Seg 最后一行有问题吗 char m ReadName printf nRead String s n m Writes OK char token token strtok m 如前所述 读取字符串打印没有问题 但

随机推荐