关于c ++:const_cast vs reinterpret_cast

const_cast vs reinterpret_cast

使用St+C++FAQ时,应使用静态映射、动态映射和重新解释?.

const-cast用于删除或向变量添加const,它是唯一可靠的、定义的和合法的删除const的方法。reinterpret_cast用于更改类型的解释。

我以一种合理的方式理解为什么一个const变量应该只使用const-cast强制转换为非const变量,但是我不能用reinterpret-cast而不是const-cast来添加const,从而找出问题的合理理由。

我知道,使用reinterpret-cast来添加constness并不明智,但使用reinterpret-cast来添加constness是一个ub还是一个潜在的定时炸弹?

我在这里感到困惑的原因是

Largely, the only guarantee you get with reinterpret_cast is that if
you cast the result back to the original type, you will get the exact
same value.

因此,如果我使用reinterpret-cast添加constness,并且您将结果重新解释为原始类型,那么它应该返回到原始类型,而不应该是ub,但这违反了一个事实,即只应使用const-cast来删除constness

另一方面,标准保证您可以使用reinterpret case添加constuness

5.2.10 Reinterpret cast (7) ......When a prvalue v of type"pointer to T1" is converted to the type"pointer to cv T2", the result is
static_cast(static_cast(v)) if both T1 and T2 are
standard-layout types (3.9) and the alignment requirements of T2 are
no stricter than those of T1........


reinterpret_cast改变了对象内数据的解释。const_cast添加或删除const限定符。数据表示和常量是正交的。所以有不同的强制转换关键字是有意义的。

So if I add constness using reinterpret_cast and if you reinterpret_cast the result back to the original type, it should result back to the original type and should not be UB, but that violates the fact that one should only use const_cast to remove the constness

甚至无法编译:

1
2
3
4
int * n = new int;
const * const_added = reinterpret_cast<const int *>(n);
int * original_type = reinterpret_cast<int*>(const_added);
    // error: reinterpret_cast from type ‘const int*’ to type ‘int*’ casts away qualifiers


你不应该把constreinterpret_cast相加。reinterpret_cast主要应该是:重新解释指针(或其他)。

换句话说,如果你从const char*char*(希望有一个糟糕的API你不能改变),那么const_cast就是你的朋友。这就是它的全部意图。

但是如果你需要从MyPODType*const char*的话,你就需要reinterpret_cast,而不需要const_cast在上面,这只是一个好处。


有一点需要记住:不能使用const_cast使const变量可写。如果常量引用引用了非常量对象,则只能使用它从常量引用中检索非常量引用。听起来很复杂?例子:

1
2
3
4
5
6
7
8
// valid:
int x;
int const& x1 = x;
const_cast<int&>(x1) = 0;
// invalid:
int const y = 42;
int const& y1 = y;
const_cast<int&>(y1) = 0;

实际上,这两者都将编译,有时甚至"工作"。但是,第二个会导致未定义的行为,并且在许多情况下,当常量对象被放置在只读内存中时,会终止程序。

也就是说,还有一些事情:reinterpret_cast是最强大的演员,也是最危险的,所以除非你必须使用它,否则不要使用它。当需要从void*sometype*时,使用static_cast。相反方向时,使用内置隐式转换或使用显式static_cast。同样地,添加或删除const,这也是隐式添加的。关于EDCOX1〔0〕,请参阅C++中的讨论,当我们更喜欢在ReCufftType中使用两个链式STATICE CAST时,讨论一个不太严格的替代方案。

乌里


是的,如您所知,const-cast意味着它将consty从特定类型中移除。

但是,当我们需要向类型添加常量时。我们有理由这么做吗?

例如,

1
2
3
4
5
void PrintAnything(void* pData)
{
    const CObject* pObject = reinterpret_cast<CObject*>(pData);
    // below is bla-bla-bla.
}

重新解释解释与"const"无关。

Const-Cast意味着两件事。第一种方法是从类型中移除常量,另一种方法是给出其代码的明确性。因为您可以使用C样式的强制转换来使用强制转换,但这不是显式的,因此不建议这样做。

它们的功能不同。这绝对是不同的。


我唯一能想到的将reinterpret cast与const ness关联起来的地方是,将const对象传递给接受空指针的API时。-

1
2
3
4
UINT ThreadFunction(void* param)
{
    const MyClass* ptr = reinterpret_cast<const MyClass*>(param);
}