- volatile
- 告诉编译器不要优化;不要去寄存器中读取该变量的值,而是要从内存中读取
- 有些时候操作系统会把硬件映射到内存中,程序通过操作内存来操作硬件(例如磁盘读写)
- volatile与多线无关,并不能保证多线程内存安全,可引用
头文件实现 - 可以与const共用,const标识此变量不能被该程序修改,volatile标识此变量可能被该程序外的因素所更改
volatile会对程序运行结果造成影响,请看以下两端代码
int main()
{
volatile const int i = 1;
cout << i << endl; //输出1
//对编译器透明的情况下,把i的值加1
__asm {
mov dword ptr[ebp - 8], 1h
}
cout << i << endl; //输出2
}
如果不加volatile,输出会不同
int main()
{
const int i = 1;
cout << i << endl; //输出1
//对编译器透明的情况下,把i的值加1
__asm {
mov dword ptr[ebp - 8], 1h
}
cout << i << endl; //输出1
}
- static_cast
用于在编译期对某种类型的变量进行强制类型转换,但没有运行时的类型检查来保证转换的安全性
static_cast
主要用法:
- 基类和派生类之间指针或引用的转换 进行上行转换(把派生类的指针或引用转换成基类表示)是安全的 进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的
- 基本数据类型的转换
- 把void指针转换成目标类型的空指针
- 把任何类型的表达式转换成void类型
int main()
{
auto a = 1;
auto b = static_cast<char>(a);
cout << typeid(a).name() << endl; //int
cout << typeid(b).name() << endl; //char
char ch = '8';
cout << ch - '\0' << endl; //56
int num = static_cast<int>(ch);
num++;
cout << num << endl; //57
///////////////////////////////////////////////////////
int *intP = new int(1);
void *charP = static_cast<void *>(intP);
void *p = nullptr;
float *fP = static_cast<float *>(p);
cout << typeid(charP).name() << endl; //void *
cout << typeid(fP).name() << endl; //float *
delete intP;
}
- const_cast
用法为:const_cast
C++ the type in a const_cast must be a pointer, reference, or pointer to member to an object type
最好不要用这种方法,因为它会产生意想不到的情况(C++中未定义的行为),如以下代码所示
int main()
{
const int a = 1;
const int* ap = &a;
cout << *ap << endl; //输出10
int b = const_cast<int&>(a); //reference
int *bp = const_cast<int*>(ap); //pointer
b = 10;
*bp = 18;
cout << b << endl; //输出10
cout << a << endl; //输出1
cout << *bp << endl; //输出18
cout << *ap << endl; //输出18
}
- reinterpret_cast
const_cast
主要有三种用途
- 改变指针或引用的类型
- 将指针或引用转换为一个足够长度的整形
- 将整型转换为指针或引用类型
int main()
{
int a = 1;
int* p = &a;
cout << p << endl; //012FF710
auto c = reinterpret_cast<int>(p);
cout << c << endl; //19920656
cout << typeid(c).name() << endl; //int
auto d = reinterpret_cast<int*>(a);
cout << d << endl; //00000001
cout << typeid(d).name() << endl; //int *
auto e = reinterpret_cast<float&>(a);
cout << e << endl; //1.4013e-45
cout << typeid(e).name() << endl; //float
}
- dynamic_cast
dynamic_cast
You cannot use dynamic_cast to convert from a non-polymorphic class (a class with no virtual functions).
You can use static_cast to perform conversions of non-polymorphic types. However, static_cast does not perform a run-time check.
// C2683.cpp
// compile with: /c
class B { };
class D : public B { };
void f(B* pb) {
D* pd1 = dynamic_cast<D*>(pb); // C2683--Error Code
D* pd1 = static_cast<D*>(pb); // OK
}
其特点如下:
- 其他三种都是编译时完成的,dynamic_cast 是运行时处理的,运行时要进行类型检查
- dynamic_cast 要求 <> 内所描述的目标类型必须为指针或引用。dynamic_cast 转换如果成功的话返回的是指向类的指针或引用,转换失败的话则会返回 nullptr
- 基类必须是多态类,必须要有虚函数
class Base
{
public:
virtual void print()
{
cout << "This is Base" << endl;
}
virtual ~Base()
{
cout << "Base's destructor called" << endl;
}
};
class derive : public Base
{
public:
void print() override
{
cout << "This is derive" << endl;
}
~derive()
{
cout << "derive's destructor called" << endl;
}
};
int main()
{
derive a;
Base* p = &a;
auto b = dynamic_cast<derive*>(p);
cout << typeid(b).name() << endl; //class derive *
if (b == nullptr)
cout << "failed - 1" << endl;
auto c = dynamic_cast<Base*>(p);
cout << typeid(c).name() << endl; //class Base *
if (c == nullptr)
cout << "failed - 2" << endl;
derive* p2 = new derive();
auto d = dynamic_cast<Base*>(p2);
cout << typeid(d).name() << endl; //class Base *
if (d == nullptr)
cout << "failed - 3" << endl;
Base* p3 = new Base();
derive* e = dynamic_cast<derive*>(p3); //class derive *
cout << typeid(e).name() << endl;
if (e == nullptr)
cout << "failed - 4" << endl; //failed - 4
delete p2;
delete p3;
//derive's destructor called
//Base's destructor called
//Base's destructor called
//derive's destructor called
//Base's destructor called
}