我正在读一本书而且我发现reinterpret_cast不应该直接使用,而是将其与无效*结合使用static_cast:
T1 * p1=...
void *pv=p1;
T2 * p2= static_cast<T2*>(pv);
Run Code Online (Sandbox Code Playgroud)
代替:
T1 * p1=...
T2 * p2= reinterpret_cast<T2*>(p1);
Run Code Online (Sandbox Code Playgroud)
但是,我找不到解释为什么这比直接演员更好.如果有人能给我一个解释或指出我的答案,我将非常感激.
提前致谢
ps我知道用的是什么reinterpret_cast,但我从未见过以这种方式使用它
在c ++ 11中,constexpr表达式不能包含重新解释转换.因此,例如,如果想要操纵浮点数中的位,比如找到数字的尾数:
constexpr unsigned int mantissa(float x) {
return ((*(unsigned int*)&x << 9) >> 9);
};
Run Code Online (Sandbox Code Playgroud)
上面的代码将无法实现constexpr.从理论上讲,我无法看到在这个或类似情况下重新解释如何与算术运算符有任何不同,但编译器(和标准)不允许它.
是否有任何巧妙的方法来解决这个限制?
我已经阅读了之前有关使用的reinterpret_cast各种问题,并且我还阅读了C++标准中的相关措辞.本质上,它归结为指针到指针reinterpret_cast操作的结果不能安全地用于除了被回送到原始指针类型之外的任何东西.
然而,在实践中,大多数现实世界的使用reinterpret_cast似乎都是基于(错误的)假设,即a reinterpret_cast与C风格的演员表相同.例如,我见过很多的代码,它使用reinterpret_cast从投char*来unsigned char*的字符集转换程序的目的.这是完全无害的,但严格来说,它不是便携式-有没有保证,一个reinterpret_cast来自char*于unsigned char*当您尝试取消引用不会崩溃您的程序unsigned char*指针.
根据标准,似乎唯一的其他实际用途reinterpret_cast有任何真正的保证,是从指针转换为整数,反之亦然.
然而,在许多情况下,我们希望(并且应该能够)在不同的指针类型之间安全地进行转换.例如:uint16_t*到新的C++ 0x char16_t*,或者实际上是指向与原始类型相同大小/对齐的基本数据类型的任何指针.然而,reinterpret_cast并不保证这应该起作用.
问题:如何安全地在指向相同大小/对齐的基本数据类型的指针之间进行转换,例如char*- > unsigned char*?既然reinterpret_cast似乎并不保证这实际上有效,那么C风格的演员是唯一安全的选择吗?
我尝试编译非常简单的代码:
struct T {
int a[3];
int b;
int c;
};
int main() {
const int as[3] = { 5, 6, 7, };
const T t {
as, 2, 3,
};
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但它给了我很奇怪的错误:
t.cpp: In function 'int main()':
t.cpp:11:5: error: array must be initialized with a brace-enclosed initializer
};
^
Run Code Online (Sandbox Code Playgroud)
根据我的理解,编译器希望我在一个地方初始化所有内容.如何单独初始化字段,然后在初始化结构时使用它们?
为什么我不能使用reinterpret_cast运算符进行这样的演员表?
enum Foo { bar, baz };
void foo(Foo)
{
}
int main()
{
// foo(0); // error: invalid conversion from 'int' to 'Foo'
// foo(reinterpret_cast<Foo>(0)); // error: invalid cast from type 'int' to type 'Foo'
foo(static_cast<Foo>(0));
foo((Foo)0);
}
Run Code Online (Sandbox Code Playgroud) 我需要写一些整数类型的单个字节.我应该使用reinterpret_cast,还是应该使用static_castvia void*?
(一个)
unsigned short v16;
char* p = static_cast<char*>(static_cast<void*>(&v16));
p[1] = ... some char value
p[0] = ... some char value
Run Code Online (Sandbox Code Playgroud)
或(b)
unsigned short v16;
char* p = reinterpret_cast<char*>(&v16);
p[1] = ... some char value
p[0] = ... some char value
Run Code Online (Sandbox Code Playgroud)
根据static_cast和reinterpret_cast对std :: aligned_storage的回答都应该是等价的 -
- 如果T1和T2都是标准布局类型,并且T2的对齐要求不比T1更严格
我倾向于reinterpret_cast为是基本上我在做什么,不是吗?
还有其他需要考虑的事情,特别是我们正在编译的Visual-C++和VC8版本吗?(x86只有atm.)
这是一个有点深奥的问题,但我很好奇以下类扩展模式在现代C++中是否合法(如,不构成UB)(出于所有目的和目的,我将讨论局限于C++ 17和后来).
template<typename T>
struct AddOne {
T add_one() const {
T const& tref = *reinterpret_cast<T const*>(this);
return tref + 1;
}
};
template<template<typename> typename E, typename T>
E<T> const& as(T const& obj) {
return reinterpret_cast<E<T> const&>(obj);
}
auto test(float x) {
return as<AddOne>(x).add_one();
}
auto test1(int x) {
return as<AddOne>(x).add_one();
}
// a main() to make this an MVCE
// will return with the exit code 16
int main(int argc, const char * argv[]) {
return test1(15);
}
Run Code Online (Sandbox Code Playgroud)
上面的代码是一个完整的例子,它在C++ …
目前我正在使用传统的c ++代码库.在此代码库中,指向对象的指针将转换为void-pointers,然后存储在c-library中.请考虑以下代码:
class interface {
public:
virtual void foo() {
std::cout << "Interface" << std::endl;}
virtual ~interface(){};
};
class debug_interface: public interface {
public:
virtual void foo() {
std::cout << "Debug Interface" << std::endl;}
};
Run Code Online (Sandbox Code Playgroud)
对象interface并debug_interface在堆上分配,地址存储在void指针中.在某些时候,指针被检索,然后再转换回基类interface.然后调用虚函数调用.看到
int main(int argc, char *argv[]){
void *handle = reinterpret_cast<void*>(new interface());
void *debug_handle = reinterpret_cast<void*>(new debug_interface());
//void *handle = new interface();
//void *debug_handle = new debug_interface();
interface *foo1 = reinterpret_cast<interface*>(handle);
interface *foo2 = reinterpret_cast<interface*>(debug_handle);
//interface *foo1 = static_cast<interface*>(handle);
//interface …Run Code Online (Sandbox Code Playgroud) 我正在查看https://en.cppreference.com/w/cpp/language/reinterpret_cast,我注意到它指定了我们可以始终转换为的合法类型:
byte*char*unsigned char*但我并没有看到void*在列表中。这是疏忽吗?我的用例需要一个,reinterpret_cast因为我是从int**转换为void*。我最终会从void*后面投射到镜头上int**。
因此,如果您从Void*转换为Type*或从Type*转换为Void*,您应该使用:
void func(void *p)
{
Params *params = static_cast<Params*>(p);
}
Run Code Online (Sandbox Code Playgroud)
要么
void func(void *p)
{
Params *params = reinterpret_cast<Params*>(p);
}
Run Code Online (Sandbox Code Playgroud)
对我来说static_cast似乎更正确,但我看到两者都用于同一目的.此外,转换的方向是否重要.即我还应该使用static_cast:
_beginthread(func,0,static_cast<void*>(params)
Run Code Online (Sandbox Code Playgroud)
我已经阅读了关于C++样式转换的其他问题但是我仍然不确定这个场景的正确方法是什么(我认为它是static_cast)