C++初阶:入门基础
1.C的第一个程序C兼容C语言绝大多数的语法所以C语言实现的hello world依旧可以运行C中需要把定义文件代码后缀改为.cpp//C兼容C语言#includestdio.hintmain(){printf(hello world\n);return0;}当然C也有一套自己的输入输出有自己的语法严格来说C版本的hello world是这样写的//C#includeiostreamusingnamespacestd;intmain(){couthello worldendl;return0;}那这里的iostream是什么呢using namespace std又是什么呢下面我们一一讲解。2.命名空间2.1 namespace的价值在C和C中变量函数和类都是大量存在的这些变量函数类的名称将都存在于全局作用域中可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化以避免命名冲突或名字污染namespace关键字的出现就是针对这种问题的。C语言项目类似下面程序这样的命名冲突是普遍存在的问题C引入namespace就是为了更好的解决这样的问题。#includestdio.h#includestdlibintran10;intmain(){// 编译报错error C2365: “rand”: 重定义以前的定义是“函数”printf(%d\n,rand);return0;}2.2 namespace的定义1.定义命名空间需要用到namespace关键字后面跟着命名空间的名字这个名字是要自己定义的名字后面接上一对{}即可{}中即为命名空间的成员命名空间的成员可以是变量函数类型等。2.namespace本质是定义出一个域这个域跟全局域局部域各自独立谁都不影响谁也就是说我在全局域中定义一个rand函数在自己定义的namespace域中定义一个rand函数这两个函数是独立的谁都不影响谁。3.C中域有函数全局域局部域命名空间域类域。域影响的是编译时语法查找一个变量/函数/类型的出处的逻辑所以有了域隔离名字冲突就解决了。局部域和全局域除了会影响编译查找逻辑还会影响变量的生命周期命名空间域和类域不会影响变量的生命周期。4.namespace只能定义在全局也可以嵌套定义。5.项目工程中多文件定义同名的namespace会认为是一个namespace,不会冲突。6.C标准库都放在一个叫std的命名空间中。下面举一些例子#includeiostreamusingnamespacestd;//定义一个命名空间域namespacehbw{//定义变量intrand10;//定义函数intAdd(inta,intb){returnab;}//定义类型structhan{inta;structhan*next;}intmain(){//这里默认访问的是全局的rand函数指针(标准库里有一个rand函数)printf(%p\n,rand);//这里指定hbw命名空间的randptintf(%d\n,hbw::rand);return0;}2.3命名空间的使用我们先看一下下面这个程序会不会报错.#includeiostreamusingnamespacestd;namespacehbw{inta1;intb0;}intmain(){printf(%d\n,a);return0;}上面这个程序是有问题的我们会疑惑上面我定义了a变量为什么还会报错原因是编译查找一个变量的声明/定义时默认只会在局部域或者在全局域查找不会到命名空间里面去查找。所以我们要使⽤命名空间中定义的变量/函数有三种⽅式1.指定命名空间访问项⽬中推荐这种⽅式。2.using将命名空间中某个成员展开项⽬中经常访问的不存在冲突的成员推荐这种⽅式。3.展开命名空间中全部成员项⽬不推荐冲突⻛险很⼤⽇常⼩练习程序为了⽅便推荐使⽤。3.C输入和输出1.是input output stream的缩写是标准的输入输出流库定义了标准的输入输出对象。2.std::cin是istream类的对象它主要面向窄字符的标准输入流。3.std::cout是ostream类的对象它主要面向窄字符的标准输出流。4.std::endl是一个函数流插入输出时相当于插入一个换行加刷新缓冲区。5.是流插入运算符是流提取运算符。6.cout/cin/endl等都属于C标准库C标准库都放在⼀个叫std(standard)的命名空间中所以要通过命名空间的使⽤⽅式去⽤他们。如using namespace std这样去使用。4.缺省参数1.缺省参数是声明或定义函数时为函数的参数指定⼀个缺省值。在调⽤该函数时如果没有指定实参则采⽤该形参的缺省值否则使⽤指定的实参缺省参数分为全缺省和半缺省参数。有些地⽅把缺省参数也叫默认参数。2.全缺省就是全部形参给缺省值半缺省就是部分形参给缺省值。C规定半缺省参数必须从右往左依次连续缺省不能间隔跳跃给缺省值。3.带缺省参数的函数调⽤C规定必须从左到右依次给实参不能跳跃给实参。4.函数声明和定义分离时缺省参数不能在函数声明和定义中同时出现规定必须函数声明给缺省值。#includeiostreamusingnamespacestd;voidfunc(inta0){coutaendl;}intmain(){func();//没有传参时使用参数的默认值就是0func(1);//传参时使用指定的实参就是1return0;}5.函数重载C⽀持在同⼀作⽤域中出现同名函数但是要求这些同名函数的形参不同可以是参数个数不同或者类型不同。这样C函数调⽤就表现出了多态⾏为使⽤更灵活。C语⾔是不⽀持同⼀作⽤域中出现同名函数的。#includeiostreamusingnamespacestd;//1.参数类型不同intAdd(intleft,intright){coutint Add(int left, int right)endl;returnleftright;}doubleAdd(doubleleft,doubleright){coutdouble Add(double left, double right)endl;returnleftright;}//2.参数个数不同voidf(){coutf()endl;}voidf(inta){coutf(int a)endl;}//3.参数类型顺序不同voidf(inta,charb){coutf(int a,char b)endl;}voidf(charb,inta){coutf(char b, int a)endl;}下面两个函数也构成重载但是调用时会报错因为存在歧义编译器不知道调用谁voidf1(){coutf1()endl;}voidf1(inta1){coutf1(int a 1)endl;}//会报错编译器不知到要调用谁6.引用6.1引用的概念和定义引⽤不是新定义⼀个变量⽽是给已存在变量取了⼀个别名编译器不会为引⽤变量开辟内存空间它和它引⽤的变量共⽤同⼀块内存空间。类型 引用别名 引用对象;C中为了避免引⼊太多的运算符会复⽤C语⾔的⼀些符号⽐如前⾯的和这⾥引⽤也和取地址使⽤了同⼀个符号⼤家注意使⽤⽅法⻆度区分就可以。#includeiostreamusingnamespacestd;intmain(){inta0;// 引⽤b和c是a的别名intba;intca;// 也可以给别名b取别名d相当于还是a的别名intdb;d;// 这⾥取地址我们看到是⼀样的coutaendl;coutbendl;coutcendl;coutdendl;return0;}6.2引用的特性1.引用在定义时必须初始化。2.一个变量可以有多个引用。3.引用一旦引用一个实体就再不能引用其他实体。#includeiostreamusingnamespacestd;intmain(){inta10;// 编译报错“ra”: 必须初始化引⽤//int ra;intba;intc20;// 这⾥并⾮让b引⽤c因为C引⽤不能改变指向// 这⾥是⼀个赋值bc;coutaendl;coutbendl;coutcendl;return0;}6.3const引用1.可以引⽤⼀个const对象但是必须⽤const引⽤。const引⽤也可以引⽤普通对象因为对象的访问权限在引⽤过程中可以缩⼩但是不能放⼤。2.不需要注意的是类似 int rb a3; double d 12.34; int rd d; 这样⼀些场景下a3的和结果保存在⼀个临时对象中 int rd d 也是类似在类型转换中会产⽣临时对象存储中间值也就是时rb和rd引⽤的都是临时对象⽽C规定临时对象具有常性所以这⾥就触发了权限放⼤必须要⽤常引⽤才可以。3.所谓临时对象就是编译器需要⼀个空间暂存表达式的求值结果时临时创建的⼀个未命名的对象C中把这个未命名对象叫做临时对象。intmain(){constinta10;// 编译报错error C2440: “初始化”: ⽆法从“const int”转换为“int ”// 这⾥的引⽤是对a访问权限的放⼤//int ra a;// 这样才可以constintraa;// 编译报错error C3892: “ra”: 不能给常量赋值//ra;// 这⾥的引⽤是对b访问权限的缩⼩intb20;constintrbb;// 编译报错error C3892: “rb”: 不能给常量赋值//rb;return0;}#includeiostreamusingnamespacestd;intmain(){inta10;constintra30;// 编译报错: “初始化”: ⽆法从“int”转换为“int ”// int rb a * 3;constintrba*3;doubled12.34;// 编译报错“初始化”: ⽆法从“double”转换为“int ”// int rd d;constintrdd;return0;}6.4指针和引用的关系C中指针和引⽤就像两个性格迥异的亲兄弟指针是哥哥引⽤是弟弟在实践中他们相辅相成功能有重叠性但是各有⾃⼰的特点互相不可替代。1.语法概念上引⽤是⼀个变量的取别名不开空间指针是存储⼀个变量地址要开空间。2.引⽤在定义时必须初始化指针建议初始化但是语法上不是必须的。3.引⽤在初始化时引⽤⼀个对象后就不能再引⽤其他对象⽽指针可以在不断地改变指向对象。4.引⽤可以直接访问指向对象指针需要解引⽤才是访问指向对象。5.sizeof中含义不同引⽤结果为引⽤类型的⼤⼩但指针始终是地址空间所占字节个数(32位平台下占4个字节64位下是8byte)。6.指针很容易出现空指针和野指针的问题引⽤很少出现引⽤使⽤起来相对更安全⼀些。7.inline1.⽤inline修饰的函数叫做内联函数编译时C编译器会在调⽤的地⽅展开内联函数这样调⽤内联函数就需要建⽴栈帧了就可以提⾼效率。2.inline对于编译器⽽⾔只是⼀个建议也就是说你加了inline编译器也可以选择在调⽤的地⽅不展开不同编译器关于inline什么情况展开各不相同因为C标准没有规定这个。inline适⽤于频繁调⽤的短⼩函数对于递归函数代码相对多⼀些的函数加上inline也会被编译器忽略。3.C语⾔实现宏函数也会在预处理时替换展开但是宏函数实现很复杂很容易出错的且不⽅便调试C设计了inline⽬的就是替代C的宏函数。4.inline不建议声明和定义分离到两个⽂件分离会导致链接错误。因为inline被展开就没有函数地址链接时会出现报错。8.nullptr1.C中NULL可能被定义为字⾯常量0或者C中被定义为⽆类型指针(void*)的常量。不论采取何种定义在使⽤空值的指针时都不可避免的会遇到⼀些⿇烦本想通过f(NULL)调⽤指针版本的f(int*)函数但是由于NULL被定义成0调⽤了f(intx)因此与程序的初衷相悖。f((void*)NULL);调⽤会报错。2.C11中引⼊nullptrnullptr是⼀个特殊的关键字nullptr是⼀种特殊类型的字⾯量它可以转换成任意其他类型的指针类型。使⽤nullptr定义空指针可以避免类型转换的问题因为nullptr只能被隐式地转换为指针类型⽽不能被转换为整数类型。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2574235.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!