1.#与##在define中的作用
1.0 宏定义中#运算符将其后面的参数转换成字符串;
如下代码:
#define TEST_1(x) cout << #x << endl
int n = 100;
TEST_1(n);
输出如下:
n
输出的是字符串化后的n,而不是其他值;
1.1 宏定义中##运算符将前后的参数进行字符串连接;
测试代码和结果如下:
#define TEST_2(x,y,z) cout<< x##y##z << endl
int main()
{TEST_2("st", "ri", "ng");
}
string
请按任意键继续. . .
2.assert断言相关认识点
2.0 本质经查是一个函数,检测条件表达式,如果为假,表示检测失败,程序会向stderr中输出一条错误信息,再调用abort函数终止程序执行。
2.1 在#include语句之前插入#define NDEBUG 可禁用assert函数
2.2 在每个assert中只检测一个条件,不要在assert中修改变量的值
测试代码如下:
int main()
{int x = 1, y = 2;assert(x > y);cout << "x > y" << endl;
}
程序直接报错了,当加#define NDEBUG 后 可忽略程序中的assert语句。
#define NDEBUG
#include "test_1.h"int main()
{int x = 1, y = 2;assert(x > y);cout << "x > y" << endl;
}
x > y
请按任意键继续. . .
3. 自增自减
3.0 如下代码在不同编译器环境下可能会产生二义性
int main()
{int i = 1;int m = (++i) + (++i) + (++i);cout << "m : " << m << endl;cout << "i : " << i << endl;
}
在本人VS2015中运行结果如下:
m : 12
i : 4
请按任意键继续. . .
而在GCC编译器中,只要有连个完整的操作数就会立即执行加法运算(本人并未亲自验证,参考自书籍《程序员面试笔记C/C++、算法、数据结构篇》。其与VS编译器执行差别图示如下:
4.0 c++中的类型转换操作符
4.0 static_case
除了基本类型外,在对象指针之间的类型转换时,可以将父类指针转换成子类指针,也可以将子类指针转换成父类。
int i = 1;
double di = static_cast<double>(i);class Base {};
class Derived : public Base {};Base * b1ptr = new Base;
Base * b2ptr = new Derived;
Derived *d1ptr = static_cast<Derived * >(b1ptr); //父指针转子指针
Derived *d2ptr = static_cast<Derived * >(b2ptr); //父指针转子指针Derived * d3ptr = new Derived;
Base * b3ptr = static_cast<Base *>(d3ptr); //子指针转父指针
4.1 dynamic_cast
只能用于对象指针建的转换,转换结果可以是引用。
在将父指针转换成子指针的过程中,需要对其背后的对象类型进行检测,以保证类型完全匹配,而static_cast不会怎么做,只有当有一个父类指针指向一个子类对象,并且父类中包含虚函数时,使用dynamic转化才会成功,否则返回空指针,如果是引用则抛出异常。
class Base { virtual void Test() {} };
class Derived : public Base {};Base * b1ptr = new Base;
Base * b2ptr = new Derived;Derived *d1ptr = dynamic_cast<Derived * >(b1ptr); //失败,d1ptr值为NULL
Derived *d2ptr = dynamic_cast<Derived * >(b2ptr); //成功Derived * d3ptr = new Derived;
Base * b3ptr = dynamic_cast<Base *>(d3ptr); //成功
int main()
{assert(d2ptr != NULL);assert(b3ptr != NULL);assert(d1ptr != NULL);
}
4.2 const_cast
在转换过程中增加或删除const属性。
class Base { };
class Derived : public Base {};const Base * b1 = new Base; //指向常量的指针
Base * const b2 = new Base; //常量指针
const Base * const b3 = new Base; //指向常量的常量指针Base * b4 = const_cast<Base *>(b1); //去掉外层const
Base * b5 = const_cast<Base *>(b2); //去掉内层const
Base * b6 = const_cast<Base *>(b3); //都去掉const Base * const b7 = const_cast<Base *>(b6);//增加外层和内层constint main()
{assert(b4 != NULL);assert(b5 != NULL);assert(b6 != NULL);assert(b7 != NULL);
}
4.3 reinterpret_cast
可以将一种类型转换成另一种类型 ,不论两个类型之间是否有继承关系。此外还可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针。
class Test1 { };
class Test2 { };Test1 * t1 = new Test1;
Test2 * t2 = reinterpret_cast<Test2 *>(t1);unsigned int n = 0x12345678;
unsigned int * p = reinterpret_cast<unsigned int *>(n);int main()
{assert(t2 != NULL);assert((int)p == 0x12345678);
}