说我想投A*,char*反之亦然,我们有两个选择(我的意思是,我们很多人认为我们有两个选择,因为两者似乎都有效!因此混乱!):
struct A
{
int age;
char name[128];
};
A a;
char *buffer = static_cast<char*>(static_cast<void*>(&a)); //choice 1
char *buffer = reinterpret_cast<char*>(&a); //choice 2
Run Code Online (Sandbox Code Playgroud)
两者都很好.
//convert back
A *pA = static_cast<A*>(static_cast<void*>(buffer)); //choice 1
A *pA = reinterpret_cast<A*>(buffer); //choice 2
Run Code Online (Sandbox Code Playgroud)
即便这样工作正常!
那么,为什么我们reinterpret_cast在C++中有两个链接 static_cast可以完成它的工作呢?
你们中的一些人可能认为这个主题与之前的主题重复,例如本文底部列出的,但事实并非如此.这些主题讨论只在理论上,但他们没有给出甚至一个例子来展示为什么reintepret_cast是真正需要的,而2 static_cast将肯定会失败.我同意,一个static_cast会失败.但两个怎么样?
如果两个链接的语法static_cast看起来很麻烦,那么我们可以编写一个函数模板,使其对程序员更友好:
template<class To, class From>
To any_cast(From v)
{
return static_cast<To>(static_cast<void*>(v));
}
Run Code Online (Sandbox Code Playgroud)
然后我们可以使用它,如:
char *buffer = any_cast<char*>(&a); …Run Code Online (Sandbox Code Playgroud) 我正在读一本书而且我发现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,但我从未见过以这种方式使用它
参考SO C++ FAQ 什么时候应该使用static_cast,dynamic_cast和reinterpret_cast?.
const_cast用于删除或添加const到变量,它是唯一可靠,定义和合法的方法来删除constness.reinterpret_cast用于更改类型的解释.
我理解为什么一个const变量应该只使用const_cast转换为非const,但我无法找出使用reinterpret_cast而不是const_cast来添加constness的问题的合理理由.
我知道使用reinterpret_cast甚至添加constness是不是很理智,但是使用reinterpret_cast来增加常量会是UB还是潜在的定时炸弹?
我在这里感到困惑的原因是因为声明
很大程度上,reinterpret_cast的唯一保证是,如果将结果转换回原始类型,您将得到完全相同的值.
因此,如果我使用reinterpret_cast添加constness,并且如果你将结果重新解释为原始类型,它应该返回原始类型而不应该是UB,但这违反了一个事实,即只应该使用const_cast来删除constness
在单独的注释中,该标准保证您可以使用重新解释案例添加Constness
5.2.10重新解释强制转换(7)......当"指向T1的指针"类型的prvalue v转换为"指向cv T2的指针"类型时,如果两个T1都为static_cast(static_cast(v))和T2是标准布局类型(3.9),T2的对齐要求不比T1更严格........
在一个变体类中,我正在处理原始存储是一个char数组:
alignas(/* the strictest alignment of all types of the variant */)
char storage[/* ... */];
Run Code Online (Sandbox Code Playgroud)
赋值运算符类似于:
template<class X>
void operator=(const X &x)
{
// ...code for clearing the storage and setting the tag for type X...
new(storage) X(x);
}
Run Code Online (Sandbox Code Playgroud)
获取存储对象的代码是:
template<class X>
const X &get()
{
// ...
return *reinterpret_cast<X *>(storage);
// ...
}
Run Code Online (Sandbox Code Playgroud)
它似乎工作,但它总是很好定义?我担心安全地解除引用指针(类型别名规则允许它吗?).
当前的实施和之间是否存在任何差异
return *static_cast<const X *>(static_cast<const void *>(storage));
Run Code Online (Sandbox Code Playgroud)
相关问题/答案:
/sf/answers/512527081/(见James Kanze的评论).
编辑
第二个问题已经有了答案:C++我们什么时候应该优先使用两个链式的static_cast而不是reinterpret_cast
哪个更好?
static_cast<T *>(static_cast<void *>(buffer));
Run Code Online (Sandbox Code Playgroud)
要么
reinterpret_cast<T *>(buffer);
Run Code Online (Sandbox Code Playgroud)
其中buffer是char *(存储器块包含类型的值T).
谁可以给我解释一下这个:
char* a;
unsigned char* b;
b = a;
// error: invalid conversion from ‘char*’ to ‘unsigned char*’
b = static_cast<unsigned char*>(a);
// error: invalid static_cast from type ‘char*’ to type ‘unsigned char*’
b = static_cast<unsigned char*>(static_cast<void*>(a));
// everything is fine
Run Code Online (Sandbox Code Playgroud)
2和3之间的区别是什么?如果将3的方法用于其他(更复杂的)类型,是否存在任何陷阱?
[编辑]有些人提到糟糕的设计等...
这个简单的例子来自一个图像库,它给出了指向图像数据的指针char*.显然,图像强度始终是正的,因此我需要将其解释为unsigned char数据.