通过重新解释强制转换创建无效引用
Creating an invalid reference via reinterpret cast
我正在尝试确定以下代码是否调用未定义的行为:
#include <iostream>
class A;
void f(A& f)
{
char* x = reinterpret_cast<char*>(&f);
for (int i = 0; i < 5; ++i)
std::cout << x[i];
}
int main(int argc, char** argue)
{
A* a = reinterpret_cast<A*>(new char[5])
f(*a);
}
我的理解是,往返char*
reinterpret_cast
是合规的,因为该标准允许使用char
和unsigned char
指针进行混叠(强调我的(:
如果程序尝试通过以下类型之一以外的左值访问对象的存储值,则行为是未定义的:
- 对象的动态类型,
- 对象的动态类型的 CV 合格版本,
- 一种类型,该类型是对应于对象的动态类型的有符号或无符号类型,
一种类型,- 该类型是与对象的动态类型的 CV 限定版本相对应的有符号或无符号类型,
- 在其成员中包含上述类型之一的聚合或联合类型(递归地包括子聚合或包含的联合的成员(,
- 一种类型,该类型是对象的动态类型的基类类型(可能符合 CV 标准(,
char
或unsigned char
类型。
但是,我不确定f(*a)
是否通过创建对无效指针的A&
引用来调用未定义的行为。决定因素似乎是"试图访问"措辞在C++标准背景下的含义。
我的直觉是,这并不构成访问,因为访问需要定义A
(在此示例中已声明,但未定义(。不幸的是,我在C++标准中找不到"访问"的具体定义:
f(*a)
调用未定义的行为吗?C++标准中的"访问"是什么?
我知道,无论答案如何,在生产代码中依赖这种行为可能是一个坏主意。我问这个问题主要是为了提高我对语言的理解。
[编辑] @SergeyA引用了标准的这一部分。我把它包括在这里是为了方便参考(强调我的(:
5.3.1/1 [expr.unary.op]
一元
*
运算符执行间接寻址:应用它的表达式应该是指向对象类型的指针,或指向函数类型的指针,结果是引用表达式指向的对象或函数的左值。如果表达式的类型是"指向T
的指针",则结果的类型是"T
"。[注意:通过指向不完整类型(cv void 除外(的指针进行间接寻址是有效的。这样获得的左值可以以有限的方式使用(例如初始化引用(;这个左值不能转换为prvalue,参见4.1。— 尾注 ]
追溯对 4.1 的引用,我们发现:
4.1/1 [转换]
非函数、非数组类型
T
的 glvalue (3.10( 可以转换为 prvalue。如果T
是不完整的类型,则需要此转换的程序格式不正确。如果 T 是非类类型,则 prvalue 的类型是T
的 cv 非限定版本。否则,prvalue 的类型为T
。当将左值到右值的转换应用于表达式时
e
,并且:
e
未可能进行评估,或e
的评估结果是e
潜在结果集合的成员ex
,ex
命名一个不被ex
使用的变量x
(3.2(不访问引用对象中包含的值。
我认为我们的答案在于*a
是否满足第二个要点。我在解析该条件时遇到问题,所以我不确定。
char* x = reinterpret_cast<char*>(&f);
有效。或者,更具体地说,允许通过x
进行访问 - 强制转换本身始终有效。
A* a = reinterpret_cast<A*>(new char[5])
无效 - 或者准确地说,通过a
访问将触发未定义的行为。
这样做的原因是,虽然通过char*
访问对象是可以的,但通过随机对象访问字符数组是不行的。标准允许第一个,但不允许第二个。
或者,通俗地说,您可以通过char*
为type*
别名,但不能通过type*
char*
别名。
编辑
我只是注意到我没有回答直接的问题(">C++标准中的"访问">是什么"(。显然,标准没有定义访问(至少,我无法找到正式定义(,但取消引用指针通常被理解为有资格访问。
- C++使用params创建线程函数会导致转换错误
- 我正在尝试使用 c++ 创建一个货币转换程序,我不知道如何继续
- 从转换后的容器元素创建离散分布
- 是否可以创建一个用户定义的文本,将字符串文本转换为 own 类型的数组?
- 创建一个函数来转换数组元素的类型并返回数组的地址
- 从c++11 time_t创建一个可转换为.net DateTime的字符串
- r-在Rcpp和C++之间转换矢量(使用Rcpp::as或Rcpp:::wrap)是否会创建一个新的矢量并复制元素
- 将 int 转换为字符串,然后连接另一个变量以创建完整扩展名,然后将其转换为 const_char*
- 如何从子项 B 创建子项 A 并转换为父级?
- C++ 异常从字符串转换为c_str会创建垃圾字符
- QT 创建器只会将第一个单词从文本编辑转换为纯文本
- 将使用基类 Ctor创建的对象转换为派生类
- Qt 创建器中的实用程序::转换::to_string_t中的链接错误
- 创建可相互转换的模板类系列
- 我创建了一个将雷亚尔转换为美元的程序,但浮点变量不正确
- 创建一个将Centigrade转换为Wahrenheit的课程,反之亦然
- 尝试使用堆栈创建队列.为什么我会遇到int转换错误的空白
- 通过强制转换创建子数组引用
- 通过重新解释强制转换创建无效引用
- 通过构造函数进行隐式类类型转换创建的临时对象何时被销毁