长沙 网站seo服务 网络服务,有哪些小公司网站,梧州做网站的公司,天津网站建设行业新闻1.命名空间 使用命名空间的目的是对标识符的名称进行本地化#xff0c;以避免命名冲突或名字污染 定义命名空间#xff0c;需要使用到namespace关键字#xff0c;后面跟命名空间的名字#xff0c;然后接一对{}即可#xff0c;{}中即为命名空间的成员 ①.普通的命名空间
n…1.命名空间 使用命名空间的目的是对标识符的名称进行本地化以避免命名冲突或名字污染 定义命名空间需要使用到namespace关键字后面跟命名空间的名字然后接一对{}即可{}中即为命名空间的成员 ①.普通的命名空间
namespace N1{//命名空间的内容既可以定义变量又可以定义函数
int a;
int Add(int left,int right){
return leftright;
}
}②.命名空间可以嵌套
namespace N1{//命名空间的内容既可以定义变量又可以定义函数
int a;
int Add(int left,int right){
return leftright;
}
namespace N3{
int c;
int d;
int sub(int left,int right){
return left-right;
}} ③.同一个工程中允许存在多个相同名称的命名空间编译器最后会合成同一个命名空间
命名空间的使用 ①.加命名空间名称和域作用限定符
int main(){
printf(%d,N::a);
return 0;
}②.使用using将命名空间中成员引入
using N::b
int main(){
pritnf(%d,N::b);
return 0;
}③.使用using namespace 命名空间名称引入 using namespace N;
using namespace N;//全部展开全部授权 using N::add;//部分展开部分授权
using namespace std; std是c标准库的命名空间 2.c输入/输出 流插入运算符 流提取运算符 couthello worldendl;endl为换行符
couthello world\n;两者效果相同 使用cout标准输出(控制台)和cin标准输入(键盘)时必须包含头文件以及std标准命名空间 使用c输入输出更加方便不需增加数据控制格式比如整形%d” 字符%c
注意cin的特点与c语言中gets有些类似gets是遇到换行符停止而cin是遇到空格tab或者换行符作为分隔符的
char arr[20]{};
cinarr;输入hello world 但由于中间存在空格故arr这个数组中只有hello没有world
3.缺省参数 缺省参数是声明或定义函数时为函数的参数指定一个默认值在调用该函数时如果没有指定实参则采用该默认值否则使用指定的实参。
void func(int a10){
coutaendl;
}
int main(){
func();//没有传参时使用参数的默认值
func(10);//传参时使用指定的实参
}分类 全缺省参数 void func(int a10;int b20;int c30){} 半缺省参数 void func(int a,int b20;int c30){} 注意①.半缺省参数必须从右往左依次来给不能间隔着给 ②.缺省参数不能在函数的声明和定义中同时出现 因为如果声明与定义位置同时出现恰巧两个位置提供的值不同那编译器就无法确定到底该用哪个缺省值 声明不给定义给 ③.缺省值必须是常量或者全局变量 //正确示例
int x 3;//全局变量
void func(int a, int b 2, int c x)
{cout a endl;cout b endl;cout c endl;
}4.函数重载:是函数的一种特殊情况C允许在同一作用域中声明几个功能类似的同名函数这些同名函数的 形参列表(参数个数 或类型或 顺序)必须不同常用来处理实现功能类似数据类型不同的问题
#include iostream
using namespace std;int Add(int x, int y)
{return x y;
}double Add(double x, double y)
{return x y;
}
int main()
{cout Add(0,1) endl;//打印01的结果cout Add(1.1,2.2) endl;//打印1.12.2的结果return 0;
}注意若仅仅只有返回值不同其他都相同则不构成函数重载。
c语言与c类似都要进行编译和链接两个过程 编译后链接前a.o的目标文件中没有Add的函数地址因为Add是在b.cpp中定义的所以Add的地址实在b.o中 链接器看到a.o调用Add但没有Add的地址就会到b.o的符号表(符号表就是函数名变量跟地址的映射)中去找Add的地址然后链接到一起。面对多个Add函数每个编译器有自己的修饰规则在gcc下的修饰规则是【_Z函数长度函数名类型首字母】。 之所以c语言无法支持重载是因为C编译器和C编译器对函数名的修饰不同
所以返回值的不会构成函数重载因为修饰规则并不会受返回值的影响。 如果函数名修饰规则带入返回值返回值能否构成重载
不能因为不知道要调用谁 5.引用 引用不是新定义一个变量而是给已存在变量取了一个别名编译器不会为引用变量开辟内存空间它和它 引用的变量共用同一块内存空间。 类型 引用变量名(对象名) 引用实体 int a10; intba; //相当于给a取了一个别名给b引用了a同一个变量取了个名字 b3;//改变b也就相当于改变a了 引用类型必须和引用实体是同种类型的 引用的特性 ①.引用在定义时必须初始化
//正确示例
int a 10;
int b a;//引用在定义时必须初始化
//错误示例
int a 10;
int b;//定义时未初始化
b a;②.一个变量可以有多个引用
int a 10;
int b a;
int c a;
int d a;③.引用一旦引用了一个实体就不能再引用其他实体c的引用不能改变指向)
int a 10;
int b a;
int c 20;
b c;//错误b已经引用了a就不能在引用c
实际效果变为b的值变为20而因为a与b相同故a的值也变成了20常引用 在引用的过程中权限可以平移可以缩小但不能放大
const int a10;
intba;会出现错误,相当于权限的放大因为在这里a为常量如果用intba;那么b可以修改但a不可以修改
const intraa;相当于权限的平移不会出错
intb10;会出现错误b为常量需要改为
const intb10;int i0;
doubledi;会出现错误因为发生类型转换时会产生一个double类型临时变量临时变量具有常性 (int到double存在隐式类型的提升而在提升的过程中系统会创建一个常量区来存放a类型提升后的结果) 需要改为
int i0;
const doubledi;int func(){
int a0;
return a;
}
intretfunc();会出现问题因为func的返回值是a的一份临时拷贝临时变量具有常性 需改成
const intretfunc();引用的使用场景 ①.做参数
void swap(intleft,intright){
int templeft;
leftright;
righttemp;
}②.做返回值 当然引用也能做返回值但是要特别注意我们返回的数据不能是函数内部创建的普通局部变量因为在函数内部定义的普通的局部变量会随着函数调用的结束而被销毁。我们返回的数据必须是被static修饰或者是动态开辟的或者是全局变量等不会随着函数调用的结束而被销毁的数据。
int count(){int n0;n;return n;
}
int main(){int retcount();return 0;
}count函数返回n的别名但是n已经销毁如果栈帧没有清楚那么结果为1否则结果为随机值
#includeiostream
using namespace std;
intAdd(int a,int b){int cab;return c;
}
int main(){intansAdd(1,2);Add(3,4);coutansendl;
}但如果再加上一句coutansendl;打印出的结果将变为随机值 因为在第一次调用coutansendl时函数传参建立栈帧调用完后被覆盖第二次调用时已经被覆盖为随机值
#includeiostream
using namespace std;
int Add(int a, int b)
{static int c a b;return c;
}int main()
{int ans Add(1,2);Add(3, 4);cout ans endl;
}为什么会出现随机值因为你在函数里定义的变量是临时变量出了函数函数是会销毁的这时它就随机指向内存中的一块空间了。所以在引用做函数返回值时最好还是给在函数中定义的变量加上static。加上static后结果将变为3。 因为第二次调用Add函数时static int cab;并不会执行而是直接return c; 但如果将该函数修改为
int Add(int a, int b)
{static int c ;cab;return c;
}总结: 传引用传参(任何时候都可以) ①.提高效率 ②.输出型参数(形参的修改影响实参) 传引用返回(出了函数作用域对象还在才可以用) ①.提高效率 ②.修改返回对象
顺序表查找和修改可以用一个函数来解决
int SLAT(struct seqlistps,int i){
return ps.a[i];
}想要修改SLAT(s,0)1;
引用和指针的区别(两者的差别主要是在语法检查层面在底层实现上并无差别) ①、引用在定义时必须初始化指针没有要求。 ②、引用在初始化时引用一个实体后就不能再引用其他实体而指针可以在任何时候指向任何一个同类型实体。 ③、没有NULL引用但有NULL指针。 ④、在sizeof中的含义不同引用的结果为引用类型的大小但指针始终是地址空间所占字节个数32位平台下占4个字节。 ⑤、引用进行自增操作就相当于实体增加1而指针进行自增操作是指针向后偏移一个类型的大小。 ⑥、有多级指针但是没有多级引用。 ⑦、访问实体的方式不同指针需要显示解引用而引用是编译器自己处理。 ⑧、引用比指针使用起来相对更安全。
7.内联函数
宏的优点 ①.一定程度上兼容不同类型没有严格的类型限制 ②.针对频繁调用小函数不再需要建立栈帧,提高了效率 缺点 ①.不方便调试宏(预编译期间进行了替换) ②.导致代码可读性差可维护性差容易误用 ③.没有类型安全的检查
例: 关于宏 如果#define add (A,B) (AB) 是错误的 因为如果出现add(ab,a|b)由于的优先级大于和|所以会先执行 改为#define add(A,B) (A)(B)
以inline函数修饰的函数叫做内联函数编译时c编译器会在调用内联函数的地方展开没有函数压栈的开销内联函数提升程序运行的速率 ①.inline是一种以空间换时间的做法省去调用函数的开销。所以代码很长/递归的函数不适宜 使用作为内联函数。 ②.inline对于编译器而言只是一个建议(内联说明只是向编译器发送一个请求编译器可以忽略这个请求)编译器会自动优化如果定义为inline的函数体内代码比较长/递归等 等编译器优化时会忽略掉内联。 例: Func 100行在100个位置调用 如果Func是内联函数那么func的指令为100x10010000行 如果Func不是内联函数那么func的指令为本身的100行和100个call调用指令 代码膨胀 ③.inline不建议声明和定义分离分离会导致链接错误另一个文件调用该函数需要地址。因为inline被展开就没有函数地址了(可以理解为内联函数在符号表中没有地址链接就会找不到。
8.auto关键字auto
int a0;
auto ba;//根据右边的值自动推导左边的值
auto ca;注意使用auto定义变量时必须对其进行初始化在编译阶段编译器需要根据初始化表达式来推导auto的实际类 型。因此auto并非是一种“类型”的声明而是一个类型声明时的“占位符”编译器在编译期会将auto替换为 变量实际的类型。
①.auto与指针和引用结合起来使用 用auto声明指针类型时用auto和auto*没有任何区别但用auto声明引用类型时则必须加 ②.在同一行定义多个变量 当在同一行声明多个变量时这些变量必须是相同的类型否则编译器将会报错因为编译器实际只对 第一个类型进行推导然后用推导出来的类型定义其他变量。 auto c3,d4.0;//该行代码会编译失败因为c和d的初始化表达类型不同
auto不能推导的场景 ①.auto做为函数的参数 ②.auto不能直接用来声明数组
基于范围的for循环 对于一个有范围的集合而言由程序员来说明循环的范围是多余的有时候还会容易犯错误。因此C11中 引入了基于范围的for循环。for循环后的括号由冒号“ ”分为两部分第一部分是范围内用于迭代的变量 第二部分则表示被迭代的范围。 范围for一般结合auto去用不管数组是什么类型
for(auto e:array)取array里的值依次赋给ee的值的改变并不会改变array里面的值要想修改必须用引用
for(autoe:array){
e*2;
}①.for循环迭代的范围必须是确定的 对于数组而言就是数组中第一个元素和最后一个元素的范围对于类而言应该提供begin和end的 方法begin和end就是for循环迭代的范围以下代码就有问题因为for的范围不确定
void testfor(int array[]){
for(autoe:array){
couteendl;
}
}10.指针空值nullptr NULL其实是一个宏在传统的C头文件(stddef.h)中可以看到如下代码
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif 可以看到NULL可能被定义为字面常量0或者被定义为无类型指针(void*)的常量。
#include iostream
using namespace std;
void Fun(int p)
{cout Fun(int) endl;
}
void Fun(int* p)
{cout Fun(int*) endl;
}
int main()
{Fun(0); //打印结果为 Fun(int)Fun(NULL); //打印结果为 Fun(int)Fun((int*)NULL); //打印结果为 Fun(int*)return 0;
}程序本意本意是想通过Fun(NULL)调用指针版本的Fun(int* p)函数但是由于NULL被定义为0Fun(NULL)最终调用的是Fun(int p)函数。
注在C98中字面常量0既可以是一个整型数字也可以是无类型的指针(void*)常量但编译器默认情况下将其看成是一个整型常量如果要将其按照指针方式来使用必须对其进行强制转换。
C11中的指针空值 对于C98中的问题C11引入了关键字nullptr。 在使用nullptr表示指针空值时不需要包含头文件因为nullptr是C11作为关键字引入的。 在C11中sizeof(nullptr)与sizeof((void*)0)所占的字节数相同大小都为4。