做网站在哪里找素材,深圳高端集团网站建设公司,超级外链工具 增加外链中,wordpress能放视频#x1f511;#x1f511;博客主页#xff1a;阿客不是客 #x1f353;#x1f353;系列专栏#xff1a;从C语言到C语言的渐深学习 欢迎来到泊舟小课堂 #x1f618;博客制作不易欢迎各位#x1f44d;点赞⭐收藏➕关注 一、什么是C
C#xff08;c plus plus#xff… 博客主页阿客不是客 系列专栏从C语言到C语言的渐深学习 欢迎来到泊舟小课堂 博客制作不易欢迎各位点赞⭐收藏➕关注 一、什么是C
Cc plus plus是一种计算机高级程序设计语言由C语言扩展升级而产生 最早于1979年由本贾尼·斯特劳斯特卢普在ATT贝尔工作室研发。
我们之前学习的C语言就是一种面向过程的语言它强调事件的具体实现过程一般以函数来具体实现。C就是一门典型的面向对象的语言它将问题分成多个对象更强调对象与对象之间的联系。它完善了C语言的许多缺陷并且引入了面向对象的程序设计思想包括面向对象的四个特性封装继承多态抽象。
无论是面向过程还是面向对象的语言都有其优缺点
面向过程面向对象优点流程化分工明确效率高结构化更清晰易维护缺点可维护性差扩展能力差开销大性能低 二、C的标准库
标准的 C 由三个重要部分组成
核心语言提供了所有构件块包括变量、数据类型和常量等等。C 标准库提供了大量的函数用于操作文件、字符串等。标准模板库STL提供了大量的方法用于操作数据结构等。
这三个部分包含了C这门语言的核心我们后面的内容就主要围绕上面三个部分展开。 三、第一个C程序
C兼容C语言的大多数语法所以C语言实现的 hello world 依旧可以运行C中需要把定义文件代码后缀改成.cppvs编译器看到是.cpp就会调用C编译器Linux下亚勇g编译不再是gcc。
当然C有一套自己的输入输出严格说C版本的 hello world 应该是这么写
// test.cpp
// 这⾥的std cout等我们都看不懂没关系下⾯我们会依次讲解
#includeiostream
using namespace std;int main()
{cout hello world\n endl;return 0;
} 四、命名空间
4.1 域作用限定符
作用域限定符: : 其作用是通知编译器应从作用域限定符左侧的名字所示的作用域中寻找右侧那个名字即指定访问哪个名字空间的哪个成员。当左侧为空时默认访问的就是全局域。
#includeiostreamint a 1;int main()
{int a 0;printf(%d\n, a);printf(%d\n, ::a);return 0;
}我们知道C语言遵循局部优先的规则即当局部变量与全局变量冲突时默认使用局部变量。而在C中我们可以通过域作用限定符来访问全局变量。
输出结果为 0 1 4.2 为什么要存在命名空间
在C/C中变量、函数和后⾯要学到的类都是⼤量存在的这些变量、函数和类的名称将都存在于全 局作⽤域中可能会导致很多冲突。使⽤命名空间的⽬的是对标识符的名称进⾏本地化以避免命名冲突或名字污染namespace关键字的出现就是针对这种问题的。
c语⾔项⽬类似下⾯程序这样的命名冲突是普遍存在的问题C引⼊namespace就是为了更好的解决这样的问题。
#includeiostream
#includestdlib.h
int rand 1;
int main()
{printf(%d\n, rand);return 0;
}当我们定义rand变量时就会与stdlib库中的rand函数出现命名冲突这在C语言中只能通过修改变量名称来解决。但是在C中我们可以就可以使用命名空间来解决。
4.3 命名空间的定义
定义命名空间需要使用到namespace关键字后面跟命名空间的名字然后接一对{}即可{}中即为命名空间的成员。
C标准库都放在⼀个叫std(standard)的命名空间中。
4.3.1 正常的命名空间定义
namespace本质是定义出⼀个域这个域跟全局域各自独立不同的域可以定义同名变量所以下⾯的rand不在冲突了。
#includeiostream
#includestdlib.h
namespace ake
{int rand 1;
}
int main()
{printf(%d\n, ake::rand);//使用域作用限定符指定作用域return 0;
}输出结果为 1 4.3.2 命名空间的嵌套定义
namespace只能定义在全局当然他还可以嵌套定义。
#includeiostream
using namespace std;
namespace ake1
{int a 1;namespace ake2//嵌套{int Add(int a, int b){return a b;}}
}
int main()
{cout ake1::a endl;//访问通过限定符依次访问cout ake1::ake2::Add(1, 1) endl;return 0;
}4.3.3 多文件中同名定义合并
在同一个工程中可以是同一个工程下的不同文件我们可以定义多个名称相同的命名空间在编译时命名空间会自动合并认为是⼀个namespace不会冲突。 namespace ake
{int a 1;
}
namespace ake
{int b 1;
}
//编译时会自动合并4.4 命名空间的使用
编译查找⼀个变量的声明/定义时默认只会在局部或者全局查找不会到命名空间⾥⾯去查找。所以 下⾯程序会编译报错。所以我们要使⽤命名空间中定义的变量/函数有三种⽅式
4.4.1 指定命名空间访问
这我们在前面已经实验演示过现在我们来演示一下访问C标准命名空间。(coutendl等常用函数都被定义在C标准命名空间std中)。
#includeiostream
int main()
{std::cout hello bite std::endl;return 0;
}指定命名空间访问项⽬中推荐这种⽅式。
4.4.2 using 部分展开
在我们书写代码时可能会频繁调用某个函数这是我们可以使用using部分展开来简化代码。使用方式为using 命名空间名称:: 成员。
#includeiostream
#includestdlib.h
namespace ake
{int a 1;int b 2;
}using ask::a;int main()
{printf(%d\n, a);printf(%d\n, a);printf(%d\n, a);printf(%d\n, a);printf(%d\n, ake::b);return 0;
}项⽬中经常访问的不存在冲突的成员推荐这种⽅式
4.4.3 using namespace 全部展开
除了部分展开自然也有全局展开。其格式为using namespace 命名空间名。
#includeiostream
#includestdlib.h
namespace ake
{int a 1;int b 2;
}using namespace ask;int main()
{printf(%d\n, a);printf(%d\n, b);return 0;
} 展开命名空间中全部成员项⽬不推荐冲突⻛险很⼤⽇常⼩练习程序为了⽅便推荐使⽤。 五、C的输入和输出
C的标准输入与输出函数是cin与cout分别对应C语言的printf与scanf。但是相较于C语言C输入输出并不需要指定占位符如%d%c等输出可以⾃动识别变量类型。
#includeiostream
using namespace std;//展开命名空间
int main()
{cout hello world endl;//endl相当于换行符cout hello world \n;cout a endl;int b 1;cout b endl;cout b endl;return 0;
}注在C中使用 cin 与 cout 以及 endl 都属于C标准库需要包含头文件iostream以及std标准命名空间。 六、缺省参数
6.1 缺省参数的使用
缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时如果没有指定实参则采用该形参缺省值否则使用指定的实参。
void func(int a 0)
{cout a endl;
}
int main()
{func(); // 没有传参时使用参数的默认值输出0func(1); // 传参时使用指定的实参输出1return 0;
}运行结果 0 1 6.2 缺省参数的分类
根据其缺省参数的个数我们我可以将缺省参数分为全缺省与半缺省。
6.2.1 全缺省
每一个参数都有缺省值。
#includeiostream
using namespace std;
void func(int a 0, int b 1, int c 2)
{cout a a endl;cout b b endl;cout c c endl endl;;
}
int main()
{func();//不穿参数func(10, 20);//半传参数func(10, 20, 30);//全传return 0;
} 6.2.2 半缺省
只有一部分参数有缺省值并且半缺省参数必须从右往左依次来给出不能间隔着给。同时传参只能从左往右依次传参。
#includeiostream
using namespace std;
void func(int a ,int b1,int c2)
{cout a a endl;cout b b endl;cout c c endl;
}
int main()
{func(10,20);//半传参数cout endl;func(10, 20, 30);//全传return 0;
}5.2.3 注意
在使用缺省参数时我们也要知道一些注意事项
1. 传参时不能间隔传参
void func(int a ,int b1,int c2)
{cout a a endl;cout b b endl;cout c c endl;
}
func(,10,20)//error2. 缺省参数不能在函数的声明和定义同时出现
//test.h
void Func(int a 10);//声明
// test.cpp
void Func(int a 20)//定义
{}七、函数重载
函数重载是函数的一种特殊情况C允许在同一作用域中声明几个功能类似的同名函数这 些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同常用来处理实现功能类似数据类型 不同的问题。
可以通过参数类型参数个数参数类型顺序来构成函数重载
int Add(int a, int b)
{return a b;
}
double Add(double a, double b)//类型不同
{return a b;
}
int Add(int a, int b, int c)//个数不同
{return a b;
}int Add(char a, int c)
{return a c;
}
int Add(int a, char c)//类型顺序不同
{return a c;
}
注意 返回值类型不同无法构成函数重载缺省值不同也不能构成函数重载 八、引用
8.1 引用的概念
引用不是新定义一个变量而是给已存在变量取了一个别名编译器不会为引用变量开辟内存空 间它和它引用的变量共用同一块内存空间 。其语法为
引用对象类型 引用变量名(对象名) 引用实体
引用类似于指针因为指向同一块空间所以改变引用变量引用实体也会改变。
#includeiostream
using namespace std;
int main()
{int a 1;int b a;//引用int c b;cout a endl;cout b endl;cout c endl;c;cout a endl;cout b endl;cout c endl;return 0;
} 8.2 引用的特性
8.2.1 引用时必须初始化
int b;//错误的必须初始化int b a;8.2.2 一个变量可以有多个引用给别名取别名
int a 1;
int b a;
int c a;//多个引用8.2.3 引用一旦引用一个实体再不能引用其他实体
int a 1;
int b a;
b 2;//这时是赋值相当于a b 2;8.3 引用的使用
8.3.1 作为函数的参数
#includeiostream
using namespace std;void swap(int a, int b)
{int z a;a b;b z;
}int main()
{int a 1, b 2;swap(a, b);cout a a endl;cout b b endl;return 0;
}
8.3.2 做函数返回值
函数的返回值是存储在一个临时的变量里面。这个变量正常情况下是不可修改的可以看作一个常量我们不能对常量进行赋值。 但使用引用作为返回值相当于返回一个引用没有中间拷贝过程和临时变量进而同时改变了引用对象func1a和被引用对象a。 #includeiostream
using namespace std;int func1(int a)
{a;return a;
}int main()
{int a 1;func1(a) 10;cout a;return 0;
}
8.3.3 错误示范
1. 引用指向的空间栈帧销毁
int func()
{int a 0;return a;
}
返回了a的引用但当离开函数函数的栈帧销毁相当于返回了一个野指针
2. 引用指向的函数多次调用
int Add(int a, int b)
{int c a b;return c;
}
int main()
{int ret Add(1, 2);Add(3, 4);cout ret endl;return 0;
}//输出什么
输出结果为7 那是因为在第二次调用函数Add(3,4)时会在原来第一次调用Add(1,2)建立栈帧的空间上建立栈帧所以返回值c的值会被重新覆盖ret是指向Add所在位置的栈帧的别名所以ret值也会发生改变。 8.4 const引用
8.4.1 对常变量的引用权限不可放大
我们可以通过 const 修饰引用来让其变为常引用。这时引用变量是不能被修改的并且只能将常变量复杂给常引用不能将常变量赋值给引用必须用const来引用。
const int a 10;
// 编译报错error C2440: “初始化”: ⽆法从“const int”转换为“int ”
// 这⾥的引⽤是对a访问权限的放⼤
//int ra a;//这样才可以
const int a 10;
// 编译报错error C3892: “ra”: 不能给常量赋值
//ra;
8.4.2 const引用普通变量权限可缩小
const 引⽤也可以引⽤普通变量因为对象的访问权限在引⽤过程中可以缩⼩但是不能放⼤。
// 这⾥的引⽤是对b访问权限的缩⼩
int b 20; const int rb b;
// 编译报错error C3892: “rb”: 不能给常量赋值
//rb;
8.4.3 const可以引用含有常性的对象
含有常性的变量包括常数函数返回值等。
const int ra 30;
int a 1, b 2;
const int ra a * 3;
const int rb a b;
double d 12.34;
// 编译报错“初始化”: ⽆法从“double”转换为“int ”
// int rd d;
int rc d;//隐式类型转换
const int rd d; 不需要注意的是类似 int ra a*3; int rb a b; int rd d; 这样⼀些场景下 a*3 的运算结果和 a 保存在⼀个临时对象中。 int rd d 也是类似引用时进行类型转换被称为隐式类型转换在类型转换中会产⽣临时对象存储中间值。也就是此时ra 和 rd 引⽤的都是临时对象⽽C规定临时对象具有常性所以这⾥ 就触发了权限放⼤必须要⽤常引⽤才可以。
所谓临时对象就是编译器需要⼀个空间暂存表达式的求值结果时临时创建的⼀个未命名的对象 C中把这个未命名对象叫做临时对象。
注
const int a 10;
int ra a;//权限放大
int rb a;//权限没有放大
a处于一块临时对象只拥有读取权限没有写入权限此时 int ra 是指向a所在的空间别名要求读取和写入的权限所以就产生了权限放大。第二个只是将 a 的值读取拷贝给 rb并没有产生权限放大。
const 引用传参在未来学习模板类的时候会有进行运用。
8.5 引用与指针的区别
语法概念上引⽤是⼀个变量的取别名不开空间指针是存储⼀个地址的变量要开空间。 引⽤在定义时必须初始化指针建议初始化但是语法上不是必须的。 引⽤在初始化时引⽤⼀个对象后就不能再引⽤其他对象⽽指针可以在不断地改变指向对象。 引⽤可以直接访问指向对象指针需要解引⽤才是访问指向对象。 sizeof中含义不同引⽤结果为引⽤类型的⼤⼩但指针始终是地址空间所占字节个数(32位平台下占4个字节64位下是8byte) 指针很容易出现空指针和野指针的问题引⽤很少出现引⽤使⽤起来相对更安全⼀些。 九、内联函数
在C语言中无论宏常量还是宏函数虽能提升程序运行效但都有易出错无法调试等缺陷。而C为了弥补这一缺陷引入了内联函数的概念代替宏函数。
以关键字inline修饰的函数叫做内联函数编译时C编译器会在调用内联函数的地方展开没有函数调用建立栈帧的开销内联函数提升程序运行的效率。
#includeiostream
using namespace std;
inline int Add(int x, int y)
{return x y;
}
int main()
{Add(1, 2);return 0;
}vs编译器 debug版本下⾯默认是不展开inline的这样⽅便调试debug版本想展开需要设置⼀下以下两个地⽅。
C/C常规——调试信息格式改成程序数据库优化——内联函数扩展改成只适用于_inline
注意
内联函数是一种以空间换时间的做法如果编译器将函数当成内联函数处理在编译阶段会用函数体替换函数调用。内联函数的优势减少了调用开销提高程序运行效率缺陷就是可能会使目标文件变大。inline对于编译器而言只是一个建议不同编译器关于inline实现机制可能不同一般建议将函数规模较小(即函数不是很长具体没有准确的说法取决于编译器内部实现)、不是递归、且频繁调用的函数采用inline修饰否则编译器会忽略inline特性。inline不能声明和定义分离分离会导致链接错误。因为inline被展开就没有函数地址了链接就会找不到。
因为内联函数会在调用时直接展开编译器默认认为不需要地址如果声明与定义分离内联函数的地址根本不会进入符号表链接时就无法找到定义的函数就会发生链接错误。 十、nullptr
在C语言中定义了一个宏NULL在传统的C头文件(stddef.h)中可以看到如下代码
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif由此我们知道NULL既可以代表数字0也可以代表空指针。这种模棱两可的定义就可能引出一些问题比如下面这段代码
#includeiostream
using namespace std;
void func(int a)
{cout func(int) endl;
}
void func(int*p)
{cout func(int*) endl;
}
//函数重载
int main()
{func(0);func(NULL);func((int*)NULL);return 0;//输出
}我们的本意可能是将NULL当成一个指针但是在默认情况下NULL被编译器当做数字0。这种问题是我们并不想看见的所以C11引入了nullptr来代替NULL。
C11中引⼊nullptrnullptr是⼀个特殊的关键字nullptr是⼀种特殊类型的字⾯量它可以转换成任意其他类型的指针类型。使⽤nullptr定义空指针可以避免类型转换的问题因为nullptr只能被隐式地转换为指针类型⽽不能被转换为整数类型。 文章转载自: http://www.morning.jwdys.cn.gov.cn.jwdys.cn http://www.morning.prgrh.cn.gov.cn.prgrh.cn http://www.morning.ccffs.cn.gov.cn.ccffs.cn http://www.morning.skqfx.cn.gov.cn.skqfx.cn http://www.morning.mdtfh.cn.gov.cn.mdtfh.cn http://www.morning.yntsr.cn.gov.cn.yntsr.cn http://www.morning.bssjp.cn.gov.cn.bssjp.cn http://www.morning.gpfuxiu.cn.gov.cn.gpfuxiu.cn http://www.morning.sjpbh.cn.gov.cn.sjpbh.cn http://www.morning.hkpyp.cn.gov.cn.hkpyp.cn http://www.morning.hmlpn.cn.gov.cn.hmlpn.cn http://www.morning.qfdyt.cn.gov.cn.qfdyt.cn http://www.morning.bswhr.cn.gov.cn.bswhr.cn http://www.morning.ptlwt.cn.gov.cn.ptlwt.cn http://www.morning.rxwnc.cn.gov.cn.rxwnc.cn http://www.morning.spxsm.cn.gov.cn.spxsm.cn http://www.morning.btwrj.cn.gov.cn.btwrj.cn http://www.morning.qhmhz.cn.gov.cn.qhmhz.cn http://www.morning.bnqcm.cn.gov.cn.bnqcm.cn http://www.morning.txzqf.cn.gov.cn.txzqf.cn http://www.morning.ydyjf.cn.gov.cn.ydyjf.cn http://www.morning.lbbrw.cn.gov.cn.lbbrw.cn http://www.morning.lfpdc.cn.gov.cn.lfpdc.cn http://www.morning.gwmjy.cn.gov.cn.gwmjy.cn http://www.morning.zqwp.cn.gov.cn.zqwp.cn http://www.morning.srndk.cn.gov.cn.srndk.cn http://www.morning.fplwz.cn.gov.cn.fplwz.cn http://www.morning.cltrx.cn.gov.cn.cltrx.cn http://www.morning.ztjhz.cn.gov.cn.ztjhz.cn http://www.morning.tpqzs.cn.gov.cn.tpqzs.cn http://www.morning.gtnyq.cn.gov.cn.gtnyq.cn http://www.morning.bqwrn.cn.gov.cn.bqwrn.cn http://www.morning.dfhkh.cn.gov.cn.dfhkh.cn http://www.morning.ykmkz.cn.gov.cn.ykmkz.cn http://www.morning.jykzy.cn.gov.cn.jykzy.cn http://www.morning.lrplh.cn.gov.cn.lrplh.cn http://www.morning.nwbnt.cn.gov.cn.nwbnt.cn http://www.morning.mkhwx.cn.gov.cn.mkhwx.cn http://www.morning.zrpbf.cn.gov.cn.zrpbf.cn http://www.morning.jjwzk.cn.gov.cn.jjwzk.cn http://www.morning.bqyb.cn.gov.cn.bqyb.cn http://www.morning.nzsx.cn.gov.cn.nzsx.cn http://www.morning.rrqbm.cn.gov.cn.rrqbm.cn http://www.morning.nj-ruike.cn.gov.cn.nj-ruike.cn http://www.morning.nkrmh.cn.gov.cn.nkrmh.cn http://www.morning.ohmyjiu.com.gov.cn.ohmyjiu.com http://www.morning.kkzwn.cn.gov.cn.kkzwn.cn http://www.morning.jgrjj.cn.gov.cn.jgrjj.cn http://www.morning.rwmp.cn.gov.cn.rwmp.cn http://www.morning.dgxrz.cn.gov.cn.dgxrz.cn http://www.morning.cgdyx.cn.gov.cn.cgdyx.cn http://www.morning.jlqn.cn.gov.cn.jlqn.cn http://www.morning.pbtdr.cn.gov.cn.pbtdr.cn http://www.morning.rdfq.cn.gov.cn.rdfq.cn http://www.morning.wftrs.cn.gov.cn.wftrs.cn http://www.morning.cknrs.cn.gov.cn.cknrs.cn http://www.morning.lbzgt.cn.gov.cn.lbzgt.cn http://www.morning.mbrbg.cn.gov.cn.mbrbg.cn http://www.morning.pctql.cn.gov.cn.pctql.cn http://www.morning.tfbpz.cn.gov.cn.tfbpz.cn http://www.morning.fkflc.cn.gov.cn.fkflc.cn http://www.morning.zkdmk.cn.gov.cn.zkdmk.cn http://www.morning.dyzbt.cn.gov.cn.dyzbt.cn http://www.morning.kqhlm.cn.gov.cn.kqhlm.cn http://www.morning.qpqb.cn.gov.cn.qpqb.cn http://www.morning.hbjqn.cn.gov.cn.hbjqn.cn http://www.morning.qwmsq.cn.gov.cn.qwmsq.cn http://www.morning.lhjmq.cn.gov.cn.lhjmq.cn http://www.morning.sgqw.cn.gov.cn.sgqw.cn http://www.morning.hyfrd.cn.gov.cn.hyfrd.cn http://www.morning.hdqqr.cn.gov.cn.hdqqr.cn http://www.morning.ryfpx.cn.gov.cn.ryfpx.cn http://www.morning.qnyf.cn.gov.cn.qnyf.cn http://www.morning.ymqrc.cn.gov.cn.ymqrc.cn http://www.morning.gwdmj.cn.gov.cn.gwdmj.cn http://www.morning.fncgw.cn.gov.cn.fncgw.cn http://www.morning.kqzxk.cn.gov.cn.kqzxk.cn http://www.morning.sglcg.cn.gov.cn.sglcg.cn http://www.morning.rqxtb.cn.gov.cn.rqxtb.cn http://www.morning.xnzmc.cn.gov.cn.xnzmc.cn