求值顺序
对于那些没有指定执行顺序的运算符来说,如果表达式指向并修改了同一个对象,将会引发错误并产生未定义的行为:
int i=0;
cout<<i<<" "<<++i<<endl;
//我们无法推断输出的值,可能是两个1,也可能是0 1
//所以上述写法是一种错误!
再举两个例子,都是左右两边都用到了同一个变量,但改变了该变量的值:
*beg = toupper(*beg++); //error! undefined behavior!
vec[i++] <= vec[i]; error! undefined behavior!
隐式类型转换
- 数组转换成指针
在大多数用到数组的表达式中,数组自动转换成指向数组首元素的指针:
int ia[10];
int *ip = ia; //ia转换成指向数组首元素的指针
当数组被用作decltype关键字的参数,或者作为取地址符(&)、sizeof及typeid等运算符的运算对象时,上述转换不会发生。
强制转换
- static_cast
static_cast
,这种强制转换只会在编译时检查。 如果编译器检测到您尝试强制转换完全不兼容的类型,则static_cast会返回错误。 您还可以使用它在基类指针和派生类指针之间强制转换,但是,编译器在无法分辨此类转换在运行时是否是安全的。
double d = 1.58947;
int i = d; // warning C4244 possible loss of data
int j = static_cast<int>(d); // No warning.
string s = static_cast<string>(d); // Error C2440:cannot convert from
// double to std:string
// No error but not necessarily safe.
Base* b = new Base();
Derived* d2 = static_cast<Derived*>(b);
- dynamic_cast
为了安全,dynamic_cast
在运行时检查基类指针和派生类指针之间的强制转换。dynamic_cast
是比static_cast
更安全的强制类型转换,但运行时检查会带来一些开销。
Base* b = new Base();
// Run-time check to determine whether b is actually a Derived*
Derived* d3 = dynamic_cast<Derived*>(b);
// If b was originally a Derived*, then d3 is a valid pointer.
if(d3)
{
// Safe to call Derived method.
cout << d3->DoSomethingMore() << endl;
}
else
{
// Run-time check failed.
cout << "d3 is null" << endl;
}
//Output: d3 is null;
- const_cast
将const_cast
转换为const
的变量,或者将非const
变量转换为const
。 通过使用这个操作符强制转换 const 就像使用C样式转换一样容易出错,不同之处在于使用const_cast
不太可能意外地执行转换。 有时候你只能强制转换const
的变量,例如,传递const
变量到一个非const
参数的函数中。 下面的示例演示如何执行此操作。
void Func(double& d) { ... }
void ConstCast()
{
const double pi = 3.14;
Func(const_cast<double&>(pi)); //No error.
}