您的位置:首页 > 编程语言 > C语言/C++

关于C++的一些细节

2010-03-11 09:09 399 查看
一.概述:
B.S.---真正的编程需要比纯粹的原理更重要!
数据+算法=程序;
通用编程: GP强调算法; OOP强调数据
可移植性和标准: 将依赖于硬件的部分放在函数模块中.
........
二.C++编程
1.关于头文件 iostream
新编译器 使用:
#include <iostream>
using namespace std;
老编译器需使用:
#include <iostream.h>
//不需使用 namespace std
**C++预处理器 以#开头的编译指令 如: #include <iostream> 将使iostream文件的内容与源代码文件内容一起发送给编译器,组成一复合文件,供之后的编译程序处理.
**using namespace std; 使得std名字空间中的所有名称都可用,如本例的 i/o: cout,cin... 类,函数,变量是C++编译器的标准组件,放在名字空间 std 中. (仅当不使用 .h 这样的头文件时)
2.C++能够使用 printf(),scanf()...标准C i/o 函数,只需包含 头文件 <stdio.h>
3.函数头 int main()
变体 int main(void)
main() // C风格
void main() //在有些系统上不能工作
4. return 0; 隐含的意思: 已经到达 main() 函数尾部
5. 使用 cout 进行C++输出
cout时一个预定义的对象 (对象是类的特定实例)
6.声明语句和变量
指出信息的存储位置(名称表示) 和 所需的内存空间 (类型来确定)
7.可以连续使用赋值操作符 如:int a = b = c = 3; 从右向左进行 赋值
8.cout的拼接版本. //好处多多
eg: cout<<"Hello"
<<yourname
<<"welcome to my blog!"<<endl
9.为程序中使用的每个函数提供原型
//编译器倾向于给函数名添加下划线前缀,提示它们对程序有最后的发言权.
10. 返回值函数
return 14 * n; //version 1
int a = 14 * n; //version 2 比version 1花的时间稍长些, 不过格式好,不易出错.
return a;
/********附: 以上只是根据我个人的情况,整理出的一些以前不清楚的知识要点. 可能其中一些还有错误或很不详细,欢迎广大"C++爱好者"来交流! *******/
三.简单变量
1.以两个下划线(underscores)或下划线和大些字母打头的名称被保留给实现使用;以一个下划线开头的名称被保留给实现用作全局标识符.
2.整型 类型位数从左至右 依次增大
bool, char, signed char, unsigned char, short, unsigned short, int, unsigned int, long, unsigned long,
还有 wchar_t
3.头文件 <climits> 中包含了关于整型限制的信息.
4.当前很多系统使用最小长度,即: short 最短为16位; long 最短32位;int 类型的长度 是计算机处理效率最高时的长度.
5.变量初始化. (若未初始化,变量的值将不确定)
eg: int n = 100; //C风格.
int n(100); //C ++风格
6.十六进制常用来表示内存地址,所以用无符号 unsigned int 比用 long 更适合表示.
7.signed char 表示范围 -128~127 unsigned char 表示范围 0~255 如果char 的取值有可能超过 127 则需用 unsigned char
8.char常量 用'A' 表示 比用 65 好. 因为只用当系统使用 ASCII编码时 二者才相等. 还有别的编码 如:EBCDIC
9.C++有 bool 类型. 用预定义的字面值 true 和 false表示.
可提升 转换为int 类型. 任何数字值或指针值都可被隐式转换为bool类型: 非○值转换为true,○转换为false
10.const限定符
eg: const int MONTHS = 12; //一定要初始化,而且初始化后不允许修改.
C用#define 预处理编译指令,做替换作用, 可以定义常量.
const 比 #define 好: 明确指定类型; 有作用域规则;可以用于更复杂的类型.
11. 浮点数 E/e 表示法 适合于非常大和非常小的数.
12. 浮点数有 : float, double, longdouble 3中类型. 默认 为 double
有效位: float 至少32位; double 至少48位,通常64位; longdouble 有 80,96,128位.
指数范围 : -37~37.
13. <float.h> 定义了浮点数的系统限制.
14. 对float C++只保证有6位有效位.
15. '/' 操作符 : 如果2个操作数 都是 int 类型 ,则结果也为 int类型
'%' 为求模操作符.
16. 类型转换: a.赋值时进行的转换. 对超出范围的 C++没有定义.
b.表达式中,有自动转换,整型提升-长度小于int的都先提升为int型,运算后 再将结果转换.
c.传递参数类型转换.
d.强制类型转换.
(long) count //C格式 long(count) //C++格式.

4.复合类型
4.1 编译器不会检查数组下标是否有效.
4.2 字符串 如: "avd" or "S" 其首字母 实际表示字符串所在内存地址
4.3 C++常用指针而不是数组来处理字符串.
eg: (cin >> year).get() ; //cin 将'/n' 留在输入队列中, 需要用无参 get() 将其丢弃, 使其不会被下次输入使用.
4.4 空行问题:
以前 C++ 版本中 getline(), get() 读取空行时,在前一条语句结束位置开始读取
当前做法: 当get() [非getline()] 读取空行后将设置失效位(failbit),接下来的输入将被阻断, 需用 cin.clear() 恢复输入.
4.5 如果输入字符串比分配空间长, getline(),get() 将余下的字符留在输入队列中, 而getline() 还设置失效位.
4.6 结构 C++声明结构变量时可省略 关键字 struct; C语言则 必须加.
4.7 有些C++老版本 不能对常规数组,结构初始化, 需加关键字 static 声明为静态变量,从而初始化. //静态变量必须初始化.
4.8 C++不提倡使用外部变量,但提倡使用外部结构声明.
4.9 将结构定义和变量声明分开,可使程序易读.
4.10 可以声明 没有名称的结构类型,但必须同时声明变量.
eg : struct {int x; int y;} point1,point2;
4.11 共用体 union ,其成员将位于相同的地址,只有一个是活动的. 也可以匿名.
4.12 枚举 enum 创建符号常量,可以替代 const.
* 枚举 类型的取值范围: 全为正数,则最小取值为0,最大取值为不小于最大值的 最小2 的乘方减一;有负数时,最小取值为,不小于负数绝对值的 最小2的乘方减一 的相反数. // 如:最大值为101,则最大取值为127.
* 只有赋值操作,无算术运算.
* 枚举量是整型,可以提升为 int ,但 int 不能自动转换为 枚举类型;如果 int 值有效[即:在枚举范围内],则可以强制转换为 枚举类型. 如果超出范围,结果讲不确定,不会出错,但不能依赖得到的结果.
* 可以创建多个值相同的符号常量.
* 同样允许匿名.
4.13 指针
* 对指针解除引用意味着获得指针指向的值.
* 间接值或接触引用操作符 '*' ,其左右空格可选: int *ptr; //C-style int* ptr; //C++style.
* 指针初始化,初始化的是地址,而不是值.
* C++创建指针时,只分配用来存储地址的内存,而没分配指针指向值的内存.
* 应将数字(整型)强制转换为 地址类型后,才能赋值: int* pt = (int*)0xB8000000;
4.14 new typename pname = new typename;
* 指针的用武之地,在运行阶段分配未命名的内存以存储值.
* new 失败则返回 0 ,可能引发 bad_alloc 异常.
** delete 只能用来释放用 new 分配的内存, 对于用声明分配的内存,不能释放.
** 不要创建两个指向同一内存块的指针,因为 可能出现 delete 两次同一内存块的情况,而这是不允许的.
* delete pname; 将释放pname 指向的内存, 但不会删除 pname 本身, 所以pname 还可以用来指向别的内存块.
* 创建/删除动态数组 eg: int* ps = new int[20]; /delete [] ps; //不能用 delete ps; 来释放.
* C ++ 将数组名解析为 地址, 数组名和指针基本等价. 只是: 指针可修改,数组名不可修改.
* 如果 用 new [] 为一个实体分配内存,则应用 delete 来释放.
4.15 用 char指针 (char*) 指向字符串常量时,指向的是字符串的地址,可用 const 来修饰,保证char指针不能修改字符串常量.
4.16 给cout 提供一指针,将打印其地址; 若给cout 提供 char* 则显示 字符串.要显示其地址,需用(int*)ps 强制转换指针为地址类型.
4.17 new delete 管理了一个内存池,与局部变量(自动变量),静态存储 内存是分开的,因而其数据生命不受程序或函数的生存时间的控制. 如果内存分配出去,但没收回,将导致其它程序不能使用该内存块,至使内存泄漏.

欢迎各位交流指正,
关于C++的一些细节[五:函数-基础] 收藏
7.函数
7.1 C++默认按值传递函数.
7.2 C++对函数返回值类型有限制,不能是数组,可以是结构和类对象,还有内置基本类型. 不过可以将数组作为结构或类对象组成部分返回.
7.3 通常函数通过将返回值复制到指定的寄存器或内存单元中来将其返回.随后,调用程序将查看内存单元.
7.4 函数原型描述了函数到编译器的接口. 这样做,编译器的效率高. 虽然可以通过扫描函数头来得到相同的信息.
7.5 原型的参数列表中,可以包括变量名,也可以不包括. 其作用相当于占位苻, 因此不必与函数定义中的变量名相同.
7.6 ANSI C 中原型可选函数名后括号为空,意味着: 不指出参数--将在后面定义参数列表.
C++ 原型比选, 仅当与接受可变参数的C函数 (如: printf()) 交互时才需要不指定参数列表, 使用'...',
如: void say_hi (...);
C++ 函数名后括号内为空与 使用关键字 void 等效. 意味着函数没有参数.
7.7 通常原型自动将被传递的参数强制转换为期望的类型.
7.8 函数和数组
int sum_arr ( int arr[], int size ); int sum_arr ( int * arr, int size );
上面2个原型作用都一样.
**注意: 在函数体内, sizeof(srr) 计算的是指针的大小.所以需要传入数组的个数.
传入的是数组地址的拷贝,arr指向的是原始数组地址,所以能在函数体内修改数组元素.
7.9 用const保护数组. 如: void show_arr ( const int num[], int size );
该声明表明指针num指向的是常量数据,不能用sum 修改该数据.
7.10 指针和const.
^ int a = 3;
^ const int * ps = $a; //*ps是const, ps不是
^ int * const pt = &a; //pt是const, *pt不是
* 常规变量的地址可以赋值给常规指针.
* 常规变量的地址可以赋值给指向 const 的指针. 如: 对于ps 而言,a 的值是常量,即ps不能用来修改 a 的值.而a的值可以使用别的方法被修改.
* 不能将const变量地址 赋值给常规指针.
* 可以将const 变量地址赋值给 const 指针.
in all: 使用const 使得函数能够处理 const 和非 const 实参, 否则将只能接受非 const 数据.
7.11 const 只能用于指向基本类型(内置类型,数组,结构,类对象)的指针.不能用于指向指针的指针.
7.12 二维数组做参数的 函数原型.
int data[3][4];
int sum ( int (*ar2)[4], int size ); //原型, (*ar2)[4] 表示一个指向由4个int 组成的数组的指针.
*ar2[4]表示一个由4个指向int的指针 组成的数组.
int sum (int ar2[][4], int size ); //原型的另一种表示.
7.13 函数与结构
* 结构名仅是结构的名称,要获得其地址需用 '&'
* 与基本类型一样,可以按值传递结构,也可以传递地址, 还可以传递引用(详细见下篇).
7.14 函数指针.
* 获取函数地址: 函数名就是 函数地址.
* 声明函数指针: 用 *pf 替换原函数原型.
如: int add ( int, int ); //原函数原型.
int (*pf)( int, int ); //函数指针 原型.
* 调用: 如: int sum = (*pf)(3,4);
也可以用 : int sum = pf(3,4);
** 函数指针数组: int (*pf[3])( int, int ); //原型.
7.15 传递参数为字符串
int ch_in_str ( const char * str, char ch );
int ch_in_str (const char str[], char ch ); //2个原型等效
字符串常量的行为与数组名相同.

8.1内联函数
* 通常做法是: 省略原型,将整个定义(函数头+函数体代码)放在本应该提供原型的地方.
* 内联函数不能递归. 也不能过大,一般只有1,2行代码.
* 与宏比较:
宏是通过文本替换来实现的. 有弊端.
内联函数是用函数体替换调用函数的地方, 省略函数调用. //在内存中的情况.
8.2 引用变量.
* 引用是已定义的变量的别名. 和原变量指向同一内存地址.
* 主要用途: 用作函数的形参,函数将使用原始数据,而不是其拷贝, 就和指针的作用一样. 主要是引用结构和类对象参数.
* 声明引用时进行初始化, 引用更接近 const 指针,一旦与某个变量关联起来,就一直"效忠"于它.
而不能想指针那样: 先声明,后赋值.
8.3 应尽可能将引用形参声明为 const.
* 可以避免无意中修改数据的编程错误.
** 使用 const 使函数能够处理 const 和非 const 实参,否则将只能接受非 const 数据.
* 使用了const引用,使函数能够正确生成并使用临时变量: 如果实参不匹配,则其行为类似于按值传递,为确保原始数据不被修改,将使用临时变量来保存值.
8.4 临时变量
* 如果接受引用参数的函数意图为修改变量,则创建临时变量将阻止这种意图的实现.
* 产生条件1: 实参的类型正确,但不是左值.
左值参数是可被引用的数据对象,如: 变量,数组元素,结构成员,引用,被解除引用的指针(*p) .
非左值: 字面常量和包含多项的表达式.
* 产生条件2: 实参的类型不正确,但可以转换为正确的类型.
8.5 当函数返回指向数据对象的引用或指针时,该对象最好在函数结束后继续存在.
* 可以让 函数返回 作为参数,传递给它的引用或指针,
typea a,b;
......
typea & fun ( typea & aa );
fun (a) = b; // 等效于: fun (a); a = b;
返回引用的函数(名)实际上是被引用的变量的别名,指向被引用的变量的内存地址
* 另一种方法: 用new 来分配新的内存来存储,
typet & clone ( typet & t ){
typet * pt = new typet;
*pt = t;
return *pt;} //返回引用, 指向新的内存地址.
8.6函数传递-引用变量使用小结:
8.6.1 不修改变量:
* 如果数据很小,如内置数据类型或小型结构,则按值传递
* 如果数据对象是数组,则使用指针,这是唯一的选择,指针声明为指向 const 的指针.
* 如果数据对象是较大结构,则使用 const 引用或 const 指针.
* 如果数据对象是类对象,则使用 const 引用,引用传递是传递类对象参数的标方式.
8.6.2 修改变量:
内置数据类型使用指针或引用;数组只能使用指针;结构体使用引用或指针;类对象使用引用,
8.7 默认函数
* 在原型设置: 默认参数值是初始化值.
* 必须从右向左添加默认值.
* 实参按从左向右的顺序依次被赋值给相应的形参,不能跳过任何参数.
8.8 函数重载(多态)
* 函数特征标: 函数参数列表,参数排列顺序都相等,函数特征标才相等. 函数特征标不同才能重载.
* 类型的引用和类型本身视为同一特征标.//从编译器角度看一样.
* 也不区分const 和非 const变量.//将非const值赋值给const变量合法,反之非法.
8.8 名称修饰苻: C++用它来跟踪每一个重载函数.
8.9 函数模板 [......待续]

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/lao_du/archive/2005/04/24/360392.aspx
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: