【问题标题】:C++ const_cast usage instead of C-style castsC++ const_cast 使用而不是 C 风格的强制转换
【发布时间】:2010-09-27 02:26:36
【问题描述】:

为什么会这样?:

  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

【问题讨论】:

  • 你能添加编译器的错误信息吗?
  • 无效使用类型为int', which is not a pointer, reference, nor a pointer-to-data-member type invalid use of const_cast with type const int'的const_cast,它不是指针、引用或指向数据成员的指针类型

标签: c++ const-cast


【解决方案1】:

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

任何类型 T 的左值都可以转换为左值或右值引用 到相同类型的 T,或多或少有 cv 限定。同样,prvalue 类类型或任何类型的 xvalue 可以转换为或多或少 cv 限定的右值引用。

意义

/* 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

【讨论】:

    【解决方案2】:

    这是一个错误,因为标准规定这是不允许的。该标准列举了const_cast 被允许进行的转换类型,并且不允许任何不在列表中的转换。它允许:

    • 指针
    • 参考文献
    • 成员指针

    由于您的类型不是其中任何一种,因此它们是不允许的。

    从好的方面来说,您提供的示例也不需要 const_cast

    【讨论】:

      【解决方案3】:
        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,因为取消引用指针将产生与 T* 相比,const T*(产生 const T)的另一种类型(产生 T)。对于引用,同样如此:T&amp; 将使用另一个 this 指针类型而不是使用 const T&amp; 访问对象。现在您真正想要归档的内容:

        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 ,你也可以写入它,然后产生未定义的行为)

      【讨论】:

      • 简单地对 const 对象进行非 const 引用真的是未定义的行为吗?我认为您实际上必须尝试对其进行修改。您的示例根本不访问 i2;它只是定义它。
      • 在任何情况下,从 (int) 到 (const int) 或从 (const int) 到 (int) 的 C 风格转换会很有用,即 const_cast 和 const_cast?
      • 肯尼,不,没有任何情况。没有内置类型的常量右值。所以这些要么是非法的,要么与“int”相同(取决于标准所说的,目前还没有在学校查过)
      • 啊。很有教育意义,谢谢。将常量转换为对非常量的引用似乎很疯狂。
      【解决方案4】:

      对于第一个错误。 const_cast 只能用于指针或引用类型。 “int”两者都不是。这可能是也可能不是 C++ 标准(找不到好的参考)。但对于某些实现,例如 MS 的 C++ 编译器,情况就是如此。

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

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

      【讨论】:

      猜你喜欢
      • 2021-06-23
      • 1970-01-01
      • 2020-09-12
      • 2023-03-16
      • 2017-01-06
      • 2012-09-25
      • 1970-01-01
      • 2016-12-17
      • 1970-01-01
      相关资源
      最近更新 更多