为什么 const_cast 需要声明你要转换的内容?
根据标准 (§5.2.11),const_cast 会丢弃 cv 限定符(const 或 volatile)。
这是一个简单的例子。首先,声明两个带有指针和引用的函数:
class Bar { ... };
void foo_ptr(Bar*);
void foo_ref(Bar&);
然后创建一个对 const 的引用:
Bar b;
const Bar& cb = b;
然后您可以使用适当的 const_cast 来调用任一函数:
foo_ptr(const_cast<Bar*>(&cb));
foo_ref(const_cast<Bar&>(cb));
这是我的问题:因为 const_cast 无法执行其他强制转换的设计目的,你要投射的内容不是很明显吗?换句话说,为什么该语言不允许我简单地说:
foo_ptr(const_cast<>(&cb));
foo_ref(const_cast<>(cb));
我只能想到以下两个原因:
a)当我尝试做一些疯狂的事情时,编译器应该阻止我,例如:
foo_ptr(const_cast<int*>(&cb));
foo_ref(const_cast<int&>(cb));
并强制我显式声明我向它投射的类型可以防止我行为不当。我发现这个(假设的)解释很弱,因为如果语言倾向于允许我写下一些错误的东西只是为了让编译器纠正我,那就太奇怪了。
b) 如果变量既是 const 又是 volatile,则可能存在歧义。在这种情况下,编译器将无法判断我是否试图放弃其中一个或另一个(或两者)。
是这个原因,还是还有其他原因?
According to the standard (§5.2.11) a const_cast casts away cv-qualifiers (const or volatile).
Here's a simple example. First you declare two functions taking a pointer and a reference:
class Bar { ... };
void foo_ptr(Bar*);
void foo_ref(Bar&);
then you create a reference-to-const:
Bar b;
const Bar& cb = b;
and then you can call either function by using the appropriate const_cast:
foo_ptr(const_cast<Bar*>(&cb));
foo_ref(const_cast<Bar&>(cb));
Here's my question: since const_cast cannot do what the other casts were designed for, isn't it obvious what you're casting to? In other words, why doesn't the language allow me to simply say:
foo_ptr(const_cast<>(&cb));
foo_ref(const_cast<>(cb));
I can think of only the following two reasons:
a) The compiler should stop me when I try to do something crazy, like:
foo_ptr(const_cast<int*>(&cb));
foo_ref(const_cast<int&>(cb));
and by forcing me to explicitly state the type I'm casting to it can then keep me from misbehaving. I find this (hypothetical) explanation weak, since it would be bizarre if the language favored allowing me to write down something wrong only to have the compiler correct me.
b) There is a possible ambiguity if the variable is both const and volatile. In that case the compiler would have no way of telling if I'm trying to cast away the one or the other (or both).
Is that why, or is there another reason?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
const_cast
可用于添加或删除const
和volatile
限定符。因此,如果允许这样的语法,则以下所有内容都将是const_cast<>(&cb)
的合法目标类型:您想要(1)。 (2) 通常很愚蠢,但可以想象它可能出现在某个地方,也许出现在某些模板代码中。 (3) 和 (4) 确实是问题所在:您可以删除
const
限定并添加易失性
资格全部通过一次演员。您可以将现有的
const_cast
替换为一对强制转换:const_cast
和volatile_cast
,并禁止 case (2) ;那么您可以在没有目标类型的情况下使用它们中的任何一个。然而,了解强制转换表达式的类型就更困难了。要了解强制转换表达式是否添加或删除限定条件,您必须知道源表达式的类型是什么。您没有理由不能使用函数模板来获得您想要的内容:
您可以轻松地为
remove_volatile
以及add_const
和add_volatile
编写类似的函数>,两者都是隐式的。const_cast
can be used to add or removeconst
andvolatile
qualifiers. So, if such a syntax were allowed, all of the following would be legitimate target types ofconst_cast<>(&cb)
:You intend (1). (2) is usually silly, but it is conceivable that it might occur somewhere, perhaps in some template code. (3) and (4) are indeed the problems: you can remove the
const
qualification and add thevolatile
qualification all with a single cast.You could replace the existing
const_cast
with a pair of casts,const_cast
andvolatile_cast
, and prohibit case (2); then you could use either of them without the target type. However, then it's more difficult to know the type of the cast expression. To know whether a cast expression adds or removes qualification, you have to know what the type of the source expression is.There's no reason you couldn't use a function template to get what you want:
You could easily write similar functions for
remove_volatile
and foradd_const
andadd_volatile
, which are both implicit.我认为詹姆斯·麦克内利斯已经谈到了重要原因。
const_cast
既可以添加也可以删除常量/易失性。你并不总是清楚你想要什么。如果我对
const foo
类型的参数调用const_cast
,这是否意味着我想将其设为非const
,或者添加易失性?或者应该只是保留 const 限定符?如果我在类型(非常量)
foo
的对象上调用它,它应该添加 const 吗?或者它应该假设我想删除 const-ness,并返回一个(非 const)foo
类型的对象?另一个原因可能只是一致性。
我们有
static_cast(x)
、dynamic_cast(x)
、reinterpret_cast(x)
所以它没有类似模板的语法的const_cast(x)
看起来很奇怪。I think James McNellis already touched on the important reasons.
const_cast
can both add and remove constness/volatileness. It's not always clear what you want.If I call
const_cast
on an argument of typeconst foo
, does that mean I want to make it non-const
, or addvolatile
to it? Or should it perhaps just keep theconst
qualifier? If I call it on an object of type (non-const)foo
, should it add const? Or should it assume that I wanted to remove const-ness, and return an object of type (non-const)foo
as well?Another reason may simply be consistency.
We have
static_cast<T>(x)
,dynamic_cast<T>(x)
,reinterpret_cast<T>(x)
so it'd look odd to have aconst_cast(x)
without the template-like syntax.主要原因是使用
const_cast
可以将 from 转换为
目标类型真的很明显吗?
The main reason is that using
const_cast
you can cast fromto
Is it really obvious what the destination type is?