[ fromfile: types.xml id: staticcast ]
static_cast<DestType>(expr)
converts the value expr to type DestType, provided that the compiler knows of an implicit conversion from expr to DestType.
All type-checking is done at compile time.
static_cast<char>('A' + 1.0); static_cast<double>(static_cast<int>(y) + 1);
The static_cast
operator converts between related types such as one pointer type to another, an enumeration type to an integral type, or a floating-point type to an integral type.
These conversions are well defined, portable, and invertible.
The compiler can apply some minimal type checking for each static_cast
.
static_cast
cannot cast away const
ness.
For that you must use const_cast<DestType>(expr)
, which creates a non-const
version of expr.
In that case, the DestType can differ from the type of expr only in the presence or absence of const/volatile
.
For an int i
, static_cast<double>(i)
creates a temporary of type double
that has the value of i
.
The variable i
itself is not changed by this cast.
Example 19.10 contains both kinds of casts.
Example 19.10. src/ansicast/m2k.cpp
// Miles are converted to kilometers. #include <QTextStream> QTextStream cin(stdin); QTextStream cout(stdout); QTextStream cerr(stderr); const double m2k = 1.609; // conversion constant inline double mi2km(int miles) { return (miles * m2k); } int main() { int miles; double kilometers; cout << "Enter distance in miles: " << flush; cin >> miles ; kilometers = mi2km(miles); cout << "This is approximately " << static_cast<int>(kilometers) << "km."<< endl; cout << "Without the cast, kilometers = " << kilometers << endl; double* dp = const_cast<double*>(&m2k); cout << "m2k: " << m2k << endl; cout << "&m2k: " << &m2k << " dp: " << dp << endl; cout << "*dp: " << *dp << endl; *dp = 1.892; cout << "Can we reach this statement? " << endl; return 0; } Output: Enter distance in miles: 23 This is approximately 37km. Without the cast, kilometers = 37.007 m2k: 1.609 &m2k: 0x8049048 dp: 0x8049048 *dp: 1.609 Segmentation fault
<include src="src/ansicast/m2k.cpp" href="src/ansicast/m2k.cpp" id="m2k" mode="cpp"/>
Here are some observations regarding the previous example.
The mixed expression miles * m2k
is implicitly widened to double
.
The safe cast static_cast<int>(kilometres)
truncates
the double
value to int
.
The cast did not change the variable kilometres
.
The results of our attempt to assign to *dp
are undefined.
const
In general, const_cast
is used only on const
-references and pointers to non-const
objects.
Using const_cast
to change const
objects has undefined behavior
because const
objects may be stored in read-only memory (which the operating system protects).
In the case of const int
, trying to change it by casting away const
depends on compiler optimization techniques, which frequently optimize them out of existance (by doing precompilation value replacement).
Example 19.11 gives some indication of the strange behavior that can occur.
Example 19.11. src/casts/constcast1.cpp
#include <iostream>
using namespace std;
int main() {
const int N = 22;
int* pN = const_cast<int*>(&N);
*pN = 33;
cout << N << '\t' << &N << endl;
cout << *pN << '\t' << pN << endl;
}
Output:
22 0xbf91cfa0
33 0xbf91cfa0
<include src="src/casts/constcast1.cpp" href="src/casts/constcast1.cpp" id="constcast1" mode="cpp"/>
The preceding output, obtained with gcc version 4.4.3, might be different on your system because the behavior is undefined.
In this example, we used const_cast
to obtain a regular pointer to a const int
.
Because the const int
is in stack storage class, attempting to change its memory does not cause a segmentation fault.
The compiler is unable to "optimize out" the int, and the const_cast
tells it not to even try.
Generated: 2012-03-02 | © 2012 Alan Ezust and Paul Ezust. |