将unique_ptr的矢量数据转换为指向常量指针

Cast vector data of unique_ptr to pointer to const pointer

提问人:jdehesa 提问时间:9/22/2023 最后编辑:Jan Schultkejdehesa 更新时间:9/23/2023 访问量:63

问:

我有一个 of,我想从 API 调用一个函数,该函数将指针指向 const 指针。将其转换为该类型是否正确?std::vectorstd::unique_ptrdata()

这个示例程序似乎在 GCC 中工作:

#include <vector>
#include <iostream>
#include <memory>

class A
{
public:
    A(int n) : n(n) {}
    int n;
};

int main()
{
    const int num = 3;
    std::vector<std::unique_ptr<A>> v;
    for (int i = 0; i < num; i++)
    {
        v.push_back(std::make_unique<A>(i));
    }
    auto vPtr = (A * const *) v.data();
    for (int i = 0; i < num; i++)
    {
        std::cout << vPtr[i]->n << std::endl;
    }
    return 0;
}

标准是否保证布局只是一个指针,因此这样做是安全的?std::unique_ptr

C++ 强制转换 stdvector unique-ptr c++-standard-library

评论

7赞 Eljay 9/22/2023
该标准保证这样做是不安全的。当我遇到这种情况时,我构建了另一个(临时)向量,其中包含从另一个向量构造的原始指针,并且它拥有智能指针。v[i].get()
2赞 Daniel Langr 9/22/2023
“标准是否保证 std::unique_ptr 的布局只是一个指针?”不是全部。不要忘记,唯一指针具有 deleter 子对象。即使无状态删除程序可以优化为不占用存储空间,但这并不能保证。
0赞 jdehesa 9/22/2023
@Eljay我也这样做了......有点不方便,如果至少 C++ 有可变长度的数组,我可以在没有堆分配的情况下调用函数,但是是的,我只需要保留额外的向量。
0赞 Eljay 9/22/2023
如果向量具有最大可能大小,则可以使用该最大大小的数组。(假设这样的大小不会在您的平台上炸毁堆栈。如果没有已知的最大大小,则阴影矢量是您可以做的最好的事情,使用 .shadow.reserve(v.size())

答:

3赞 Caleth 9/22/2023 #1

不,这是别名冲突。A 不是原始指针。std::unique_ptr

“似乎在 GCC 中有效”在 C++ 中并不安全。你的代码有未定义的行为,“似乎有效”是最糟糕的症状,因为它可能会在没有通知的情况下突然变成“以最不合时宜的方式中断”。

评论

0赞 Jan Schultke 9/23/2023
OP 的代码可以定义明确,但假设是标准布局。标准不保证这一点,因此这不是安全的假设,但称其为没有星号的严格混叠违规也是不正确的。std::unique_ptr
0赞 Caleth 9/23/2023
@JanSchultke您仍然必须尊重演员的混叠,但这里的情况并非如此,我们正在添加const
0赞 Jan Schultke 9/23/2023
C 样式的演员也可以充当 ,所以这很好。由于 const-correctness,不允许在此处隐式添加,但允许通过强制转换这样做。无论如何,const 对 OP 的代码没有任何影响,也不会使它或多或少成为 UB。这一切都归结为是否是标准布局。const_castconststd::unique_ptr
0赞 Caleth 9/23/2023
标准布局允许您在不违反锯齿的情况下进行,但它不会让您在不违反锯齿的情况下进行reinterpret_castconst_cast
1赞 Caleth 9/24/2023
@JanSchultke添加 const 与严格别名并非无关。这是次要的,也假设这是标准布局std::unique_ptr