高质量程序设计指南c++/c语言(15)--编译时和运行时的不同

摘要: 我们把编译预处理器、编译器和连接器工作的阶段合成“编译时”。语言中有些构造仅仅在编译时起作用,而有些构造是在“运行时”起作用的,分清楚这些构造对于程序设计很重要。例如,预编译伪指令、类定义、外部对象声明、函数原型、标识符、各种修饰符号(const、static)及类成员的访问说明符和连接规范、调用规范等,仅在编译器进行语法检查、语义检查和生成目标文件及连接的时候起作用的,可在执行程序中不存在这些东西。容器越界访问、虚函数动态决议、函数动态连接、动态内存分配、异常处理和RTTI则是在运行时才会出现和发挥作用的。举两个例子:(1)#include<iostream>using name 阅读全文
posted @ 2013-04-27 21:40 江在路上2 阅读(171) 评论(0) 推荐(0) 编辑

高质量程序设计指南c++/c语言(14)--函数指针

摘要: 在注册一个回调函数的时候,我们常常使用函数指针。c++/c的连接器在连接程序的时候必须把函数体的首地址绑定到对该函数调用语句上,因此函数地址必须在编译时就确定下来,也就是编译器为函数体生成代码的时候。这样的话,函数地址就是一个编译时常量。函数指针就是指向函数体的指针,其值就是函数体的首地址。而在源代码层面,函数名就代表函数的首地址,所以把函数名直接指派给一个同类型的函数指针而不需要使用“&”运算符。typedef int (* FunPtr)(const char *);FunPtr fp1 = puts;double (* fp3)(double) = sqrt; 通过函数指针来调用 阅读全文
posted @ 2013-04-27 21:20 江在路上2 阅读(196) 评论(0) 推荐(0) 编辑

高质量程序设计指南c++/c语言(13)--数组

摘要: 1、 对于多维数组传递,必须指出除了第一维之外的所有维的长度,例如void output(const int a[][20], int line){ count << siezof(a) << endl; //4 for(int i=0; i<line; i++) { for(int j=0; j<20; j++) { cout << a[i][j] << endl; } }}2、多维数组的动态创建和删除不能简单地使用一个元素类型的指针来接受动态创建的多维数组的返回地址。这是因为:一个多维数组在语义上并不等... 阅读全文
posted @ 2013-04-27 19:00 江在路上2 阅读(161) 评论(0) 推荐(0) 编辑

高质量程序设计指南c++/c语言(12)--指针

摘要: 指针的类型为一个类型名和一个字符“*”的组合,虽然类型名和“*”的组合是一种指针类型,但是编译器解释的时候,“*”是和其后的变量名结合的。例如: int* a,b,c;编译器理解为: int *a, b,c;即只有a是int类型的指针,而b和c仍然是int类型的变量。指针的值是int类型的,可以赋给它任何整数值,包括负数#include<iostream>using namespace std;int main(void){ int *pInt = NULL; pInt = reinterpret_cast<int *>(-0x0024FFE4); cout <. 阅读全文
posted @ 2013-04-27 16:00 江在路上2 阅读(148) 评论(0) 推荐(0) 编辑

高质量程序设计指南c++/c语言(11)--成员对齐

摘要: 对于成员对齐,我们要设法减少对象中的空洞,宁愿让末尾留下空洞也不要让中间留下空洞,尽量使所有成员连续存放,并且减少末尾的填充字节。要按照从大到小的顺序从前到后依次声明每一个数据成员,并且尽量使用较小的成员对齐方式。这样,对象的布局及各个成员的偏移就不会随着对齐方式的改变而改变,其布局非常稳定。这一点在一定程度上增加了复合类型的可移植性及其对象的二进制兼容性。这一点在那些包含多个模块的应用中定义模块之间的接口数据类型时是很重要的。如果不同模块恰好使用了不同的对齐方式,而模块间共享的复合数据类型没有显示的指定对齐方式,那么程序出错甚至崩溃的风险就会增加。且看下面的例子: 假设应用程序有一个... 阅读全文
posted @ 2013-04-27 15:32 江在路上2 阅读(253) 评论(0) 推荐(0) 编辑

高质量程序设计指南c++/c语言(10)--位域和自然对齐

摘要: 处于对齐的考虑(将对象的大小调整到机器字的整数倍),每个对象的存储空间中可能会存在填充字节,这些字节单元不会初始化,而是具有上次使用留下来的随机值。显然,每个对象填补字节的内容是不会相同的。这就是说,如果编译器支持使用逐位比较的默认方法来比较同类型对象,结果肯定是不对的。1、位域 c语言位域各成员的类型必须是int\unsigned int\signed int等类型,c++还允许使用long、char。但是不允许使用指针类型或者浮点类型作为位域的成员类型。struct Student{ unsigned int day:5; unsigned int :0; unsigned... 阅读全文
posted @ 2013-04-27 14:13 江在路上2 阅读(220) 评论(0) 推荐(0) 编辑

高质量程序设计指南c++/c语言(9)--类型转换函数

摘要: class Point{public: Point(float x);private: float m_x;};Point p1 = 10.5; //直接调用Point::Point(float x)p1 = 20.5; //先调用Point::Point(floatx)把20.5转换成一个Point临时对象,然后再调用默认的operator=赋值函数。又是通过构造函数进行的隐含类型转换可能会损害程序的可理解性,如下面:class MyString{public: MyString(int n, char c='\0');private: char *m_data... 阅读全文
posted @ 2013-04-26 22:12 江在路上2 阅读(160) 评论(0) 推荐(0) 编辑

高质量程序设计指南c++/c语言(8)--内联函数

摘要: 宏替换发生在编译预处理阶段,使用宏可以加快执行速度,但是宏有一些缺点(1)容易出错,预处理器在复制宏代码时常常产生想不到的边际效应(2)另一个缺点是不能调试,但是内联函数是可以调试的。内联函数不是也像宏一样进行代码展开吗?怎么能调试呢?其实内联函数的可调试不是说它展开后还能调试,而是在程序的调试版本里它根本没有实现内联。在发行版里,编译器才会实施真正的内联。 内联发生在编译阶段,对任何内联函数,编译器在符号表里放入函数的声明,包括名字、参数、返回值类型(符号表是编译器用来收集和保存字面常量和某些符号常量的地方)。如果编译器没有发现内联函数存在错误,那么该函数的代码也被放入符号表里。在... 阅读全文
posted @ 2013-04-26 21:41 江在路上2 阅读(132) 评论(0) 推荐(0) 编辑

高质量程序设计指南c++/c语言(7)--重载++

摘要: #include<iostream>using namespace std;class Integer{public: Integer(int data):m_data(data){} Integer & operator++() //前置版本 ++i { m_data++; return *this; } Integer operator++(int) //后置版本 i++ { Integer temp = *this; m_data++; return temp; }priva... 阅读全文
posted @ 2013-04-26 21:25 江在路上2 阅读(102) 评论(0) 推荐(0) 编辑

高质量程序设计指南c++/c语言(6)--拷贝构造函数和赋值函数

摘要: 如果不主动编写拷贝构造函数和赋值函数,编译器就会以按成员拷贝的方式自动生成相应的默认函数。倘若类中含有指针成员或引用成员,那么这两个默认的函数就可能隐含错误。 假设String类有一个char *m_data的数据成员,a.m_data的内容为“hello”,b.m_data的内容也为“hello”,现在将a赋值给b,默认赋值函数的按成员拷贝意味着执行b.m_data = a.m_data。这会造成3个错误(1)b.m_data原来持有的内存没有释放。(2)b.m_data和a.m_data指向同一块内存,任何一方的改动会影响其他一方。(3)在对象被析构时,m_data被delete了两... 阅读全文
posted @ 2013-04-26 16:56 江在路上2 阅读(225) 评论(0) 推荐(0) 编辑