将指针强制转换为指向数组的指针是否被视为 UB?

yat*_*nai 0 c++

最近我想知道是否可以显式定义指针是什么并显式确定其类型。假设我们在返回 us 的new operator表达式中使用了 the 。但我想保护自己免受可能的错误的影响,并希望明确指示指针中元素的大小。auto* x = new int[4];int*

我发现你可以定义一个指向形式数组的指针T(*name)[size]。这种指针转换算UB吗?我们似乎通过添加信息来保留基本指针类型,这是否违反了类型别名的规则?

int main()
{
     auto* p = new int[10];
     decltype(auto) n = (int(*)[10])(p);
     *n[1]=1;
}
Run Code Online (Sandbox Code Playgroud)

Art*_*yer 6

这种 C 风格的强制(int(*)[10]) p转换相当于reinterpret_cast.

reinterpret_cast很难合作。您正式拥有 UB,其中n是“指向int[10]”类型的指针,但它是指向数组第一个元素的指针(与 相同p),而不是数组本身。这些被定义为具有相同的地址,但这没有关系,n不能用于访问数组。

这就是函数的用武之地std::launder:您可以清洗该指针以获取指向实际数组对象而不是其第一个元素的指针。

int main()
{
     using ten_ints = int[10];
     int* p = new ten_ints;
     ten_ints* n = std::launder(reinterpret_cast<ten_ints*>(p));
     (*n)[1]=1;
     assert(p[1] == 1);
}
Run Code Online (Sandbox Code Playgroud)

但这很难处理,您应该想出替代解决方案,例如:

int main() {
    {
        using ten_ints = std::array<int, 10>;
        ten_ints* p = new ten_ints;  // Pointer to std::array, doesn't "decay"
    }
    {
        using ten_ints = std::span<int, 10>;
        int* p = new int[10];
        ten_ints s(p, 10);  // Use a span of size 10
    }
}
Run Code Online (Sandbox Code Playgroud)

...当然不是new完全使用,而是使用另一个类似的容器std::vector来容纳大小。