首页 文章

将void指针转换为特定类型指针时,哪个转换符号更好,static_cast或reinterpret_cast? [重复]

提问于
浏览
34

可能重复:在将void *转换为任何内容时,我应该使用static_cast还是reinterpret_cast

在这个程序中,我有 void * 作为参数,并希望将其转换为特定类型 . 但我不知道使用哪个"casting symbol" . static_castreinterpret_cast 都有效 . 哪一个更好?标准C推荐哪一个?

typedef struct
{
    int a;
}A, *PA;

int foo(void* a)                // the real type of a is A*
{
    A* pA = static_cast<A*>(a); // or A* pA = reinterpret_cast<A*>(a);?
    return pA->a;
}

这是

A* pA = static_cast<A*>(a);

要么

A* pA = reinterpret_cast<A*>(a);

更合适吗?

6 回答

  • 1

    如果要沿类层次结构进行转换,请使用 dynamic_cast - 它会检查以确保实际对象与您要转换的类型兼容 .

  • 47

    您可能通过隐式转换获得了 void* ,因此您应该使用 static_cast ,因为它最接近隐式转换 .

  • 0

    reinterpret_cast 将强制将 void* 转换为目标数据类型 . 它不保证任何安全性,您的程序可能会崩溃,因为底层对象可能是任何东西 .

    例如,您可以将 myclass* 类型转换为 void* ,然后使用 reinterpret_cast 将其转换为 yourclass* ,这可能具有完全不同的布局 .

    所以它更好,建议使用 static_cast

  • 1

    都不是 . 为什么你首先将指针传递给void?在C中,'s fairly common due to lack of alternatives, but in C++ there'几乎从来没有理由做任何类似的事情 .

    编辑:@Dan O提高了使用强制转换来最小化生成代码的可能性 . 对于那些没有谈论的人,考虑像 std::vector 这样的东西 - 当你定义(例如) std::vector<A *>std::vector<B *> 时,你可以通过定义一个只容纳 void * 的容器来解决这个问题,然后再回到从容器中检索项目时的正确类型 .

    首先,这通常是最好的过早优化(并且通常会变成悲观) . 尽管如此,有时候它才有意义 . 但是,如果它确实如此将强制转换限制在一个地方,但是为 void * 的伪通用容器创建一个模板化的前端:

    template <class T>
    pointer_container {
        std::vector <void *> data;
    public:
        T *operator[](size_t index) { return static_cast<T *>(data[index]); }
    };
    

    现在,我们现在有一个演员阵容 . 是的,为了直接回答原始问题, static_cast 是适用于这种情况的正确答案 .

    回到MS-DOS时代(例如)这样的代码相当常见 . 然而,今天,这种代码风格完全没有意义 .

    现在,OP已经表示他将实施它的工作 . 我没有看到这个代码的其余部分,所以它肯定地说他们认为这种情况至少99%的可能性 . {1413620_d} . 因此,我坚持原来的答案 . 发布的答案刚刚说了"static_cast",没有任何关于避免演员阵容的事情是真正无益的 . 虽然演员真的可以证明是错误的反应和错误的答案 .

    我会更进一步:如果一个关于投射的问题未能提供关于为什么投射是不可避免的证据,那么任何人都应该考虑的唯一建议是完全消除投射的建议 . 它可能(在极少数情况下)表明,演员阵容绝对是例外,而不是规则 .

  • -1

    static_cast 更适合将 void* 转换为其他类型的指针 .

    当两种类型之间存在自然,直观的转换时, static_cast 是首选,无需保证在运行时工作 . 例如,您可以使用 static_cast 将基类指针转换为派生类指针,这种转换在某些情况下是有意义的,但在运行时才能验证 . 类似地,您可以使用 static_castint 转换为 char ,这是明确定义的,但在执行时可能会导致精度损失 .

    另一方面, reinterpret_cast 是一个铸造操作员,旨在进行从根本上说不安全或不便携的转换 . 例如,您可以使用 reinterpret_castvoid * 转换为 int ,如果您的系统恰好有 sizeof (void*)sizeof (int) ,它将正常工作 . 您还可以使用 reinterpret_castfloat* 转换为 int* ,反之亦然,这是特定于平台的,因为 floatint 的特定表示不能保证彼此具有任何共同点 .

    简而言之,如果您发现自己正在进行转换,其中转换具有逻辑意义,但可能不一定在运行时成功,请避免 reinterpret_cast . static_cast 是一个很好的选择,如果你有一些预先知道演员表将在运行时工作,并与编译器通信"I know that this might not work, but at least it makes sense and I have a reason to believe it will correctly do the right thing at runtime."然后编译器可以检查演员表是否在相关类型之间,报告编译时错误,如果这不是'这种情况 . 使用 reinterpret_cast 执行指针转换可以完全绕过编译时安全检查 .

    在某些情况下,您可能希望使用 dynamic_cast 而不是 static_cast ,但这些情况主要涉及类层次结构中的强制转换,并且(很少)直接涉及 void* .

    至于哪一个是规范首选,两者都没有被过度提及为"the right one to use"(或者至少,我不记得其中一个被提到这种方式 . )但是,我认为规范要求你使用 static_cast 而不是 reinterpret_cast . 例如,当使用C风格的演员表时,如

    A* ptr = (A*) myVoidPointer;
    

    尝试的转换运算符的顺序总是尝试在 reinterpret_cast 之前使用 static_cast ,这是您想要的行为,因为 reinterpret_cast 不能保证是可移植的 .

  • -1

    请使用 static_cast . 只有在极少数情况下最罕见的情况下,没有其他办法使用 reinterpret_cast .

相关问题