使用c 中的static_cast施放数组参考的指针是合法的吗?
Is it legal to cast a pointer to array reference using static_cast in C++?
我有一个指针T * pValues
,我想将其视为 T (&values)[N]
在此答案中
T (&values)[N] = *static_cast<T(*)[N]>(static_cast<void*>(pValues));
我对此的担忧。在他的示例中,pValues
以以下方式初始化
T theValues[N];
T * pValues = theValues;
我的问题是,如果pValues
来自以下任何构造,则铸造构建体是否合法:
1:
T theValues[N + M]; // M > 0
T * pValues = theValues;
2:
T * pValues = new T[N + M]; // M >= 0
简短答案:您是对的。仅当pValues
是T[N]
型,并且您提到的两种情况(不同的大小,动态分配的数组)很可能导致不确定的行为。。
关于static_cast
的好处是,在编译时间内进行了一些其他检查,因此,如果您做错了什么,编译器会抱怨它(与丑陋的C风格铸件相比,您几乎可以做任何事情),例如:
struct A { int i; };
struct C { double d; };
int main() {
A a;
// C* c = (C*) &a; // possible to compile, but leads to undefined behavior
C* c = static_cast<C*>(&a);
}
会给你: invalid static_cast from type ‘A*’ to type ‘C*’
在这种情况下,您将其投入到void*
中,从编译时间可以进行的支票的角度来看,几乎对任何事物都是合法的,反之亦然:void*
也可以恢复到几乎所有物品,也可以将static_cast
完全没有用,因为这些检查变得毫无用处。
对于上一个示例:
C* c = static_cast<C*>(static_cast<void*>(&a));
不比:
更好C* c = (C*) &a;
,并且很可能会导致该指针的使用不正确,不确定的行为。
换句话说:
A arr[N];
A (&ref)[N] = *static_cast<A(*)[N]>(&arr);
是安全的,就可以了。但是,一旦您开始滥用static_cast<void*>
,就无法确保实际发生的事情,因为甚至类似:
C *pC = new C;
A (&ref2)[N] = *static_cast<A(*)[N]>(static_cast<void*>(&pC));
成为可能。
,因为C 17至少所显示的表达式不安全,即使pValues
是指向数组的第一个元素的指针,并且数组与完全匹配的类型(包括axcat尺寸),无论是从变量声明或拨打new
的调用中获得的。(如果不满足这些标准,无论以下情况如何。)
数组及其第一个元素不是 pointer-interconvertible ,因此reinterpret_cast
(相当于两个static_casts
至void*
)不能将一个指针值施加到另一个指针值的指针值。p>因此,static_cast<T(*)[N]>(static_cast<void*>(pValues))
仍将指向数组的第一个元素,而不是数组对象本身。
由于类型/值不匹配,因此该指针的限制是未定义的。
可以使用std::launder
对此进行纠正,这可能会更改reinterpret_cast
不能的指针值。具体而言,以下可能是明确的:
T (&values)[N] = *std::launder(static_cast<T(*)[N]>(static_cast<void*>(pValues)));
或等效
T (&values)[N] = *std::launder(reinterpret_cast<T(*)[N]>(pValues));
但是,只有当std::launder
返回的指针不能用于访问无法通过原始pValues
指针访问的任何字节。如果数组是一个完整的对象,则可以满足这一点,例如如果阵列是二维数组的子阵列,则不满意。
有关确切的可及性条件,请参见https://en.cppreference.com/w/cpp/utility/launder。
- 我可以有一个 ELI5 作为参考和指针以及何时使用它们吗?
- 类的方法和对象。参考?智能指针?简单的初始化?
- 我正在学习C++,我不能使用指针访问参考吗?(举个例子)
- 使用指针向量到参考向量是非法的吗?
- 函数参数绑定通过参考与传递指针传递数组的规则
- 参考参考static_cast的成本和指向指针static_cast的指针
- 函数采用原始指针试图通过错误msg中概述的参考来接受指针
- 为什么即使传递给函数作为参考,指针也未被分配
- 为什么通用参考概念不适用于函数指针的地图插入
- 是指代指针正交的参考文献
- 超载函数既不按值,也不是通过参考来对象,而是将撤销的指针换成对象
- 从参考中获取的指针可以在定义明确的C 中取无效
- 指针与参考示例,在什么情况下更好
- 为什么要拿参考的地址给我一个第二等级的指针
- 如何提升::序列化指针和参考
- 在范围外丢失指针参考
- 将std ::向量作为指针参考
- 从指针参考C 创建一个新对象
- 从基本指针/参考调用正确的免费功能
- 在操作员过载的情况下处理悬空指针/参考