几个编程注意知识点的汇总.docx
- 文档编号:25667526
- 上传时间:2023-06-11
- 格式:DOCX
- 页数:12
- 大小:60.02KB
几个编程注意知识点的汇总.docx
《几个编程注意知识点的汇总.docx》由会员分享,可在线阅读,更多相关《几个编程注意知识点的汇总.docx(12页珍藏版)》请在冰豆网上搜索。
几个编程注意知识点的汇总
引用(Reference)与指针
Moakap
引用是一个现有对象的别名。
引用与指针的区别:
1.不存在空引用;
2.必须初始化;
初始化要求:
当一个引用初始化时,它所指向的那个对象必须存在。
3.引用对象不可改变;
一旦一个引用被初始化去指向一个特定的对象,那么在该引用的整个生命周期内,都被绑定到用于初始化的那个对象上。
常量引用于非常量引用
常引用的作用:
1)禁止引用对象被修改;
2)省略临时对象拷贝等操作,提高效率;
初始化:
一个指向非常量的引用是不可以用字面值或临时值进行初始化的:
Int&a=123;//错误
指向常量的引用可以使用字面值初始化:
Constint&a=123;//OK.
此时,引用变量实际上被指向“采用该字面值初始化”的一个临时位置。
即a并不是指向123,而是指向一个采用123初始化的、类型为int的临时变量。
本文来自CSDN博客,转载请标明出处:
【编程基础】程序的执行过程
要理解一个程序的执行过程,首先要理解什么是编译器。
我们用C语言写的程序,计算机只能识别机器语言(二进制指令),计算机并不能理解。
因此,必须将C语言转换为机器语言。
编译器就是用来实现这一功能的。
编译器将源代码文件按照一定的对应规则映射程计算机能够识别的二进制指令。
关于源文件、目标文件和可执行文件
源文件:
保存源代码的文件(*.c,*.cpp)
目标文件:
编译器根据源文件创建的机器语言指令成为目标代码,包含目标代码的磁盘文件即目标文件。
一般为(*.obj)文件,Linux下为(*.o)文件。
编译完源代码后生成的目标文件并不能直接执行。
一般我们编写的程序都回引用基本的库函数,因此在运行程序之前还要把库函用定义好的目标代码替换,这个过程称为链接。
就是把自己写的源代码的目标文件与库函数的目标文件组合起来,生成最终的可执行文件。
链接由链接器完成。
Static关键字用法总结
最近经历了一些笔试和面试,经常会被问到static关键字的作用,感觉虽然知道一些,但每次回答的都不够满意,今天在网上查了一下,总结总结,恩,以备后用!
static关键字是C,C++中都存在的关键字。
static从字面理解,是“静态的“的意思,与此相对应的,应该是“动态的“。
static的作用主要有以下3个:
1、扩展生存期;
2、限制作用域;
3、唯一性;
1、扩展生存期
这一点主要是针对普通局部变量和static局部变量来说的。
声明为static的局部变量的生存期不再是当前作用域,而是整个程序的生存期。
在程序中,常用内存类型主要有堆、栈和静态存储区。
要理解static局部变量就必须首先理解这三种内存类型。
在C/C++中,局部变量按照存储形式可分为三种auto,static,register
(谭浩强,第174-175页)
局部变量的默认类型都是auto,从栈中分配内存。
auto的含义是由程序自动控制变量的生存周期,通常指的就是变量在进入其作用域的时候被分配,离开其作用域的时候被释放。
而static变量,不管是局部还是全局,都存放在静态存储区。
表面意思就是不auto,变量在程序初始化时被分配,直到程序退出前才被释放;也就是static是按照程序的生命周期来分配释放变量的,而不是变量自己的生命周期.如果在main前设置断点,然后查看static变量,已经被初始化,也就是说static在执行main函数前已经被初始化。
也就是在程序初始化时被分配。
--------------------------------------------------------------------------------------------------------------------------
堆:
由程序员自己分配释放(用malloc和free,或new和delete) ,如果我们不手动释放,那就要到程序结束才释放。
如果对分配的空间在不用的时候不释放而一味的分配,那么可能会引起内存泄漏,其容量取决于虚拟内存,较大。
栈:
由编译器自动分配释放,其中存放在主调函数中被调函数的下一句代码、函数参数和局部变量,容量有限,较小。
静态存储区:
由在编译时由编译器分配,由系统释放,其中存放的是全局变量、static变量和常量.
区别:
1) 堆是由低地址向高地址扩展,栈是由高地址向低地址扩展。
2) 堆是不连续的空间,栈是连续的空间。
3) 在申请空间后,栈的分配要比堆的快。
对于堆,先遍历存放空闲存储地址的链表、修改链表、再进行分配;对于栈,只要剩下的可用空间足够,就可分配到,如果不够,那么就会报告栈溢出。
4) 栈的生命期最短,到函数调用结束时;静态存储区的生命期最长,到程序结束时;堆中的生命期是到被我们手动释放时(如果整个过程中都不手动释放,那就到程序结束时)。
--------------------------------------------------------------------------------------------------------------------------
2、限制作用域
这一点相对于普通全局变量和static全局变量来说的。
对于全局变量而言,不论是普通全局变量还是static全局变量,其存储区都是静态存储区,因此在内存分配上没有什么区别。
区别在于:
1) 普通的全局变量和函数,其作用域为整个程序或项目,外部文件(其它cpp文件)可以通过extern关键字访问该变量和函数。
一般不提倡这种用法,如果要在多个cpp文件间共享数据,应该将数据声明为extern类型。
在头文件里声明为extern:
externintg_value; //注意,不要初始化值!
然后在其中任何一个包含该头文件的cpp中初始化(一次)就好:
intg_value=0; //初始化一样不要extern修饰,因为extern也是声明性关键字;
然后所有包含该头文件的cpp文件都可以用g_value这个名字访问相同的一个变量;
2) static全局变量和函数,其作用域为当前cpp文件,其它的cpp文件不能访问该变量和函数。
如果有两个cpp文件声明了同名的全局静态变量,那么他们实际上是独立的两个变量。
static函数的好处是不同的人编写不同的函数时,不用担心自己定义的函数,是否会与其它文件中的函数同名。
头文件中的static变量
如果在一个头文件中声明:
staticintg_vaule=0;
那么会为每个包含该头文件的cpp都创建一个全局变量,但他们都是独立的;所以也不建议这样的写法,一样不明确需要怎样使用这个变量,因为只是创建了一组同名而不同作用域的变量。
3、数据唯一性
这是C++对static关键字的重用。
主要指静态数据成员/成员函数。
表示属于一个类而不是属于此类的任何特定对象的变量和函数.这是与普通成员函数的最大区别,也是其应用所在,比如在对某一个类的对象进行计数时,计数生成多少个类的实例,就可以用到静态数据成员.在这里面,static既不是限定作用域的,也不是扩展生存期的作用,而是指示变量/函数在此类中的唯一性.这也是”属于一个类而不是属于此类的任何特定对象的变量和函数”的含义.因为它是对整个类来说是唯一的,因此不可能属于某一个实例对象的.(针对静态数据成员而言,成员函数不管是否是static,在内存中只有一个副本,普通成员函数调用时,需要传入this指针,static成员函数调用时,没有this指针.)
static数据成员的初始化:
(1)初始化在类体外进行,而前面不加static,以免与一般静态变量或对象相混淆。
(2)初始化时不加该成员的访问权限控制符private,public等。
(3)初始化时使用作用域运算符来标明它所属类,因此,静态数据成员是类的成员,而不是对象的成员。
(4)静态数据成员是静态存储的,它是静态生存期,必须对它进行初始化。
Static成员函数
静态成员函数和静态数据成员一样,它们都属于类的静态成员,它们都不是对象成员。
因此,对静态成员的引用不需要用对象名。
静态成员函数仅能访问静态的数据成员,不能访问非静态的数据成员,也不能访问非静态的成员函数,这是由于静态的成员函数没有this指针。
++]#ifndef,#define用法收藏
文件中的#ifndef
头件的中的#ifndef,这是一个很关键的东西。
比如你有两个C文件,这两个C文件都include了同一个头文件。
而编译时,这两个C文件要一同编译成一个可运行文件,于是问题来了,大量的声明冲突。
还是把头文件的内容都放在#ifndef和#endif中吧。
不管你的头文件会不会被多个文件引用,你都要加上这个。
一般格式是这样的:
#ifndef<标识>
#define<标识>
......
#endif
<标识>在理论上来说可以是自由命名的,但每个头文件的这个“标识”都应该是唯一的。
标识的命名规则一般是头文件名全大写,前后加下划线,并把文件名中的“.”也变成下划线,如:
stdio.h
#ifndef_STDIO_H_
#define_STDIO_H_
......
#endif
2.在#ifndef中定义变量出现的问题(一般不定义在#ifndef中)。
#ifndefAAA
#defineAAA
inti;
...
#endif
里面有一个变量定义
在vc中链接时就出现了i重复定义的错误,而在c中成功编译。
结论:
(1).当你第一个使用这个头的.cpp文件生成.obj的时候,inti在里面定义了当另外一个使用这个的.cpp再次[单独]生成.obj的时候,inti又被定义然后两个obj被另外一个.cpp也include这个头的,连接在一起,就会出现重复定义.
(2).把源程序文件扩展名改成.c后,VC按照C语言的语法对源程序进行编译,而不是C++。
在C语言中,若是遇到多个inti,则自动认为其中一个是定义,其他的是声明。
(3).C语言和C++语言连接结果不同,可能(猜测)时在进行编译的时候,C++语言将全局
变量默认为强符号,所以连接出错。
C语言则依照是否初始化进行强弱的判断的。
(参考)
解决方法:
(1).把源程序文件扩展名改成.c。
(2).推荐解决方案:
.h中只声明externinti;在.cpp中定义
#ifndef__X_H__
#define__X_H__
externinti;
#endif//__X_H__
inti;
注意问题:
(1).变量一般不要定义在.h文件中。
一般情况下,源程序中所有的行都参加编译。
但是有时希望对其中一部分内容只在满足一定条件才进行编译,也就是对一部分内容指定编译的条件,这就是“条件编译”。
有时,希望当满足某条件时对一组语句进行编译,而当条件不满足时则编译另一组语句。
条件编译命令最常见的形式为:
#ifdef标识符
程序段1
#else
程序段2
#endif
它的作用是:
当标识符已经被定义过(一般是用#define命令定义),则对程序段1进行编译,否则编译程序段2。
其中#else部分也可以没有,即:
#ifdef
程序段1
#denif
这里的“程序段”可以是语句组,也可以是命令行。
这种条件编译可以提高C源程序的通用性。
如果一个C源程序在不同计算机系统上系统上运行,而不同的计算机又有一定的差异。
例如,我们有一个数据类型,在Windows平台中,应该使用long类型表示,而在其他平台应该使用float表示,这样往往需要对源程序作必要的修改,这就降低了程序的通用性。
可以用以下的条件编译:
#ifdefWINDOWS
#defineMYTYPElong
#else
#defineMYTYPEfloat
#endif
如果在Windows上编译程序,则可以在程序的开始加上
#defineWINDOWS
这样则编译下面的命令行:
#defineMYTYPElong
如果在这组条件编译命令之前曾出现以下命令行:
#defineWINDOWS0
则预编译后程序中的MYTYPE都用float代替。
这样,源程序可以不必作任何修改就可以用于不同类型的计算机系统。
当然以上介绍的只是一种简单的情况,可以根据此思路设其它的条件编译
例如,在调试程序时,常常希望输出一些所需的信息,而在调试完成后不再输出这些信息。
可以在源程序中插入以下的条件编译段:
#ifdefDEBUG
print("device_open(%p)",file);
#endif
如果在它的前面有以下命令行:
#defineDEBUG
则在程序运行时输出file指针的值,以便调试分析。
调试完成后只需将这个define命令行删除即可。
有人可能觉得不用条件编译也可达此目的,即在调试时加一批printf语句,调试后一一将printf语句删除去。
的确,这是可以的。
但是,当调试时加的printf语句比较多时,修改的工作量是很大的。
用条件编译,则不必一一删改printf语句,只需删除前面的一条“#defineDEBUG”命令即可,这时所有的用DEBUG作标识符的条件编译段都使其中的printf语句不起作用,即起统一控制的作用,如同一个“开关”一样。
有时也采用下面的形式:
#ifndef标识符
程序段1
#else
程序段2
#endif
只是第一行与第一种形式不同:
将“ifdef”改为“ifndef”。
它的作用是:
若标识符未被定义则编译程序段1,否则编译程序段2。
这种形式与第一种形式的作用相反。
以上两种形式用法差不多,根据需要任选一种,视方便而定。
还有一种形式,就是#if后面的是一个表达式,而不是一个简单的标识符:
#if表达式
程序段1
#else
程序段2
#endif
它的作用是:
当指定的表达式值为真(非零)时就编译程序段1,否则编译程序段2。
可以事先给定一定条件,使程序在不同的条件下执行不同的功能。
作用范围就是当前文件啊。
因为编译是以cpp或c文件位单位的嘛。
还以这个为例:
//正常代码
#ifdef_DEBUG
TRACE("Someinformation");
#else
//Nowisreleaseversion,sodonothing
#endif
//正常代码
编译时是先把所有的预编译处理展开(比如宏)再编译,所以Debug模式下,编译时的代码是:
//正常代码
TRACE("Someinformation");
//正常代码
Release模式下的代码是:
//正常代码
//正常代码
如何编写高效的C++函数
——MoaKap的C++学习笔记
编写函数是C++编程中最基本的过程.但如何编写高效的函数,就有很多要注意的东西了.下面总结一下编写C++函数时的几条基本思想。
1、用重用的思想编写函数
1)函数中不输出
要使函数具有高的重用性,就要禁止在函数中输出结果,这样可以避免调用函数时不必要的输出。
同时,不同的开发环境其输出环境也不尽相同。
2)花时间处理当前可能不需要的输入
在函数编写过程中,当前可能并不需要某些变量的值,但考虑到函数以后的可用性,应该尽量所有输入都写出来,这样有利于在不同环境中调用函数。
3)检查所有输入的合法性
对函数的每个输入(参数),都要检查其合法性。
保证函数能够正常返回。
2、为一个函数编写注释
注释包括各个参数的意义、函数的功能描述等。
可以在实现函数之前,先完成函数的注释,然后根据功能实现函数。
3、返回值问题
在有多个分支的函数中,确保每一个分支都有返回值。
4、参数设计
尽量为每一个参数设计明了的参数名,使程序阅读者能够通过参数名得知参数的意义。
5、减少调用函数带来的负作用
如上述说的在函数中显示处理结果就是一个典型的负作用。
尽量不修改外部变量。
6、过程
无返回值的函数,也叫做过程。
最后,在编写程序时要遵循:
尽量少使用全局变量。
全局变量也可以用来在不同函数之间传递变量,但若使用了过多的全局变量,则所写的代码将很难维护和扩展。
经验法则是,每1000行代码不应该超过两个全局变量。
使用参数和类来传递信息。
若使用很多的变量,则程序就会变得很冗长。
这时,可以设计使相关变量聚集在一起的类,这样可以大大减少程序的长度。
函数功能应该尽量简单,要善于将复杂的功能分解成多个简单的函数。
每个函数长度不超过一屏(50行以内)。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 几个 编程 注意 知识点 汇总