C++中使用const_cast替代C风格的类型转换

11
为什么会出现以下情况?
  const int i0 = 5;
//int       i1 = const_cast<int>(i0);       // compilation error
  int       i2 = (int)i0;                   // okay

  int       i3 = 5;
//const int i4 = const_cast<const int>(i3); // compilation error
  const int i5 = (const int)i3;             // okay

你能添加编译器的错误信息吗? - Dmitry Khalatov
const_cast 的使用无效,因为 `int' 不是指针、引用或指向数据成员的指针类型。const_cast 的使用无效,因为 `const int' 不是指针、引用或指向数据成员的指针类型。 - kenny laitin
4个回答

23
  const int i0 = 5;
//int       i1 = const_cast<int>(i0);       // compilation error
  int       i2 = (int)i0;                   // okay

  int       i3 = 5;
//const int i4 = const_cast<const int>(i3); // compilation error
  const int i5 = (const int)i3;             // okay

编译错误是由于您没有去掉const或添加const造成的。相反,您复制了i0。对于该操作,根本不需要转换:
int i1 = i0;
const int i4 = i3;

你转换的类型应该是一个指针或引用。否则,使用const_cast就没有意义,因为你可以直接复制它。例如,对于指针,你可以取消const修饰,因为解引用指针会产生另一种类型的 (产生)和 (产生)。对于引用,也是同样的道理:将使用另一种this指针类型访问对象,而< const T&> 使用const修饰。现在你真正想要实现的是什么:
  const int i0 = 5;
//int &     i1 = const_cast<int&>(i0);      // okay (but dangerous)
  int &     i2 = (int&)i0;                  // okay (but dangerous)

  int       i3 = 5;
//const int&i4 = const_cast<const int&>(i3); // ok now and valid!
  const int&i5 = (const int&)i3;             // okay too!

上述情况可能导致未定义的行为,当您通过非const引用写入原本是const的对象时(实际上,仅仅进行强制类型转换和读取本身不会导致未定义的行为。但如果您去掉const并写入它,则会产生未定义的行为)。

仅仅拥有一个非常量引用指向一个常量对象真的算是未定义行为吗?我原以为你必须试图修改它。你的例子根本没有访问i2,只是定义了它。 - Rob Kennedy
在哪些情况下,从(int)到(const int)或从(const int)到(int)的C风格转换会有用,因为不允许使用const_cast<int>和const_cast<const int>? - kenny laitin
Kenny,没有这种情况。内置类型的常量rvalue不存在。所以那些要么是非法的,要么就和“int”一样(取决于标准规定,我目前正在上学,还没有查过)。 - Johannes Schaub - litb
啊,非常有教育意义,谢谢。将常量转换为非常量的引用似乎就像疯狂一样。 - Dasaru

5

错误是因为标准规定不允许这样做。标准列举了const_cast允许进行的转换类型,除此以外的转换都被禁止。合法的转换类型包括:

  • 指针
  • 引用
  • 成员指针

由于您的类型不属于以上任何一种类型,所以它们是不允许的。

不过好消息是,您提供的示例也不需要使用const_cast


1

关于第一个错误,const_cast只能用于指针或引用类型。"int"不是其中之一。这可能符合C++标准(找不到好的参考资料),但对于某些实现如MS的C++编译器来说是这样的。

关于第二个错误,const_cast只能用于删除const或volatile限定符,而不能添加它。

参考资料:http://msdn.microsoft.com/en-us/library/bz6at95h(VS.80).aspx


2
const_cast运算符(仅限C++) const_cast运算符用于向类型添加或删除const或volatile修饰符。来源:http://publib.boulder.ibm.com/infocenter/compbgpl/v9v111/index.jsp?topic=/com.ibm.xlcpp9.bg.doc/language_ref/keyword_const_cast.htm - kenny laitin

0
根据CPP Reference,结果必须是指针或引用。当使用指针时,输入也需要是指针。对于引用,您可以将变量作为输入,并将引用作为输出。该页面说:

任何类型T的lvalue都可以转换为相同类型T的lvalue或rvalue引用,更或者少了cv限定符。同样,类类型的prvalue或任何类型的xvalue可以转换为更或者少了cv限定符的rvalue引用。

意思是:
/* lvalue can be converted to lvalue or rvalue references  */
int& test1 = const_cast<int&>(var);   // lvalue to l-ref; same works for class type
int&& test2 = const_cast<int&&>(var); // lvalue to r-ref; same works for class type
/* prvalues: restriction on built-in types to allow some compiler optimization */
//int&& test5 = const_cast<int&&>(1);            // prvalue of built-in not allowed
A&& test6 = const_cast<A&&>(A());                // prvalue of class type allowed
/* xvalue can be converted to rvalue references */
int&& test8 = const_cast<int&&>(std::move(var)); //xvalue of built-in
A&& test8 = const_cast<A&&>(std::move(A()));     // xvalue of class

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接