- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
考虑这个 union :
union A{
int a;
struct{
int b;
} c;
};
c
和 a
不是 layout-compatibles类型,因此无法读取 b
的值通过a
:
A x;
x.c.b=10;
x.a+x.a; //undefined behaviour (UB)
对于试验 1 和试验 2,请参阅 this question
现在让我们使用std::launder
对于它似乎不是故意的:
A x;
x.a=10;
auto p = &x.a; //(1)
x.c.b=12; //(2)
p = std::launder(p); //(2')
*p+*p; //(3) UB?
可以 std::launder
改变什么?根据[ptr.launder] :
template <class T> constexpr T* launder(T* p) noexcept;
Requires:
p
represents the address A of a byte in memory. An object X that is within its lifetime and whose type is similar toT
is located at the address A. All bytes of storage that would be reachable through the result are reachable throughp
(see below).Returns: A value of type
T *
that points to X.Remarks: An invocation of this function may be used in a core constant expression whenever the value of its argument may be used in a core constant expression. A byte of storage is reachable through a pointer value that points to an object Y if it is within the storage occupied by Y, an object that is pointer-interconvertible with Y, or the immediately-enclosing array object if Y is an array element. The program is ill-formed if T is a function type or cv void.
加粗的句子强调了一件困扰我的事情。如果p
是一个无效的指针值,如何可以访问存储的任何字节?另一方面,这样的阅读std::launder
就是不可用。
否则,可以p
在 (2) 处的值是一个指针值,表示存储区域,如 [basic.life] 中的“注释”中所述。 :
If these conditions are not met, a pointer to the new object can be obtained from a pointer that represents the address of its storage by calling
std::launder
([support.dynamic]).
最佳答案
注释中明确允许。
basic.life
contains the following rule这使得 std::launder
变得不必要了:
If, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, a new object is created at the storage location which the original object occupied, a pointer that pointed to the original object, a reference that referred to the original object, or the name of the original object will automatically refer to the new object and, once the lifetime of the new object has started, can be used to manipulate the new object, if:
- the storage for the new object exactly overlays the storage location which the original object occupied, and
- the new object is of the same type as the original object (ignoring the top-level cv-qualifiers), and
- the type of the original object is not const-qualified, and, if a class type, does not contain any non-static data member whose type is const-qualified or a reference type, and
- neither the original object nor the new object is a potentially-overlapping subobject.
[ Note: If these conditions are not met, a pointer to the new object can be obtained from a pointer that represents the address of its storage by calling
std::launder
. — end note ]
这种“新对象在原始对象占用的存储位置创建”的情况显然适用于此,因为:
An object is created ... when implicitly changing the active member of a union...
满足所有项目符号条件,如"potentially overlapping subobject"指的是基类子对象, union 成员不是。 (在您链接到的版本中,该项目符号直接提到了基类子对象。)
然而,即使这个解释要针对 union 而改变,该注释特别提到 std::launder
绕过了这个限制。
请注意,旧版本的标准从该规则中排除了子对象......但注释清楚地表明 std::launder
也可以绕过该问题。
关于c++ - 使用 std::launder 从指向非事件 union 成员的指针获取指向事件 union 成员的指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56308110/
自从我的问题here无法自信地回答,我在这里再次询问,希望有人确切知道: 指向 union 的指针和包含指向其元素的指针的 union 之间有什么区别(除了语法之外)吗? this中生成的程序集示例是
在 C 语言中,是否可以在另一个 union 体中定义一个 union 体?如果不是,为什么不可能?或者如果可以,可以在哪里使用? 最佳答案 假设您要定义: union myun { int x;
在 C 中,是否可以在另一个 union 中定义一个 union ?如果不是,为什么不可能?或者如果是,它可以在哪里使用? 最佳答案 假设你想定义: union myun { int x; s
我正在阅读一些代码并发现如下内容: typedef union { int int32; int boolean; time_t date; char *string;
我正在学习Lua,我更愿意使用冒号(:)作为方法。不幸的是,它并非在所有地方都有效。看我的代码: 设置= {} 本地mt = {} 函数Set:new(m) 本地集= {} setmetatable(
我遇到了一些性能问题,我有如下查询: SELECT * FROM Foo UNION SELECT * FROM Boo UNION SELECT * FROM Koo 我确信 Koo 不会返回任何重
This question already has answers here: C++ Structure Initialization (16个答案) 上个月关闭。 我正在尝试将一些用于嵌入式目标的
UNION 和 UNION ALL 有什么区别? 最佳答案 UNION 删除重复记录(结果中的所有列都相同),UNION ALL 则不会。 使用 UNION 而不是 UNION ALL 时会影响性能,
我想在两个表上使用联合运算符。我希望结果集消除由联合创建的重复值,但不消除表中预先存在的重复值。考虑这段代码... select b from (values (1), (2), (2
我知道 UNION 会删除重复项,但即使没有重复项也会更改结果顺序。 我有两个 select 语句,任何地方都没有 order by 语句 我想将它们合并或不合并(全部) 即 SELECT A UNI
基本上,我有一个 struct foo { /* variable denoting active member of union */ enum whichmembe
我有一个大规模查询,用于对许多表(每个表有数千行)执行 UNION ALL,然后在返回之前输出到临时表。 旧形式: SELECT * FROM (SELECT `a` AS `Human rea
UNION 和 UNION ALL 有什么区别? 最佳答案 UNION 删除重复记录(结果中的所有列都相同),UNION ALL 则不会。 使用 UNION 而不是 UNION ALL 时会影响性能,
如果我有两个 union 行结构: struct A { A() {} ~A() {} union { vector vi; vector db
考虑下面的代码,我已经写了: #include #include union myAccess { uint16_t access16; struct { uint
我想弄清楚你从 C99 中对齐变量的地役权中得到了什么: Exception to strict aliasing rule in C from 6.5.2.3 Structure and union
我正在通过 UNION 或 UNION ALL 从多个表中选择一列外键。 当重复无关紧要时,通常建议使用 UNION ALL 而不是 UNION 来解决性能问题。但是,在我的调用 PHP 脚本中,循环
在 C++ 中,union 可以包含静态成员,在类的情况下,这些成员属于一个类,因此对所有对象都是通用的。 union U { long l; int i; static long
任何人都可以提及普通和匿名 union (或结构)之间的区别吗?我刚找到一个: 不能在匿名 union 中定义函数。 最佳答案 您不需要点运算符“.”访问匿名 union 元素。 #include
我可能把这个复杂化了.. 我正在尝试在 Arduino 上用 C 语言为嵌入式应用程序制作一个相当可重用的分层菜单系统。我有结构来表示不同类型的菜单项,包括那些子菜单,以及这些菜单项的 union 是
我是一名优秀的程序员,十分优秀!