简体   繁体   中英

C++ const_cast usage instead of C-style casts

Why is the following?:

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

The compilation errors are caused because you don't cast const away/add const. Instead, you copy i0. For that operation, no cast is required at all:

int i1 = i0;
const int i4 = i3;

The type you cast to should actually be a pointer or reference. Otherwise, using const_cast doesn't make sense since you could straight copy it. For pointers, for example, you can cast away the const, because dereferencing the pointer will yield another type for a const T* (yields const T ) than for a T* (yields T ). For references, the same is true: T& will access the object using another this pointer type than using const T& . Now what you really wanted to archive:

  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!

The above can lead to undefined behavior, when you write to an originally const object through a reference to non-const (actually, merely casting and reading it isn't undefined behavior in itself. But if you're casting away const, you may also write to it, which then yields the undefined behavior)

It's an error because the standard says it's not allowed. The standard enumerates the kinds of conversions that const_cast is allowed to do, and it disallows anything not on the list. It allows the following:

  • Pointers
  • References
  • Member-pointers

Since your types aren't any of those, they're not allowed.

On the bright side, the examples you gave don't need const_cast , either.

For the first error. const_cast can only be used on pointer or reference types. "int" is neither. This may or may not be the C++ standard (couldn't find a good reference). But it is the case for certain implementations such as MS's C++ compiler.

For the second error. const_cast can only be used to remove a const or volatile qualifier not add it.

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

According to CPP Reference , the result has to be pointer or references. When using pointer, the input also needs to be a pointer. For references, you can the variables as inputs, and reference as output. The page says:

lvalue of any type T may be converted to a lvalue or rvalue reference to the same type T, more or less cv-qualified. Likewise, a prvalue of class type or an xvalue of any type may be converted to a more or less cv-qualified rvalue reference.

meaning

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM