初识C++
在C的基础上对不足的弥补:如面向对象的特性,泛型函数,同名函数的重载与命名空间
namespace
C语言中的命名冲突
与库函数,变量的冲突
不同作用域 变量名之间的冲突
namespace xxn
{
namespace xxxn
{
int a=0;
}
int add=0;
void base();
}
命名空间中可以定义不同变量与函数,且可以嵌套使用
使用::域作用限定符进行不同变量和函数的调用
std::cout<<"hello world"<<endl;
xxn::add-0;
xxn::xxxn::a=1;
在文件的不同位置或不用文件中定义的同名命名空间,其内容会进行合并
展开命名空间作为默认命名空间, 调用函数或变量时可以不调用域作用限定符,将会在全局与该命名空间中寻找
using namespace xxn;
流插入作用符
<<,输出时会自动识别类型
流输入函数,搭配流插入作用符使用
换行符endl
std::cout<<"hello world"<<std::endl;
std::cout<<"hello world\n";
流提取作用符
,提取时自动识别类型
流提取函数,搭配流提取作用符使用
std::cin>> a>>b;
指定展开,可以展开库中常用的几个函数或变量
using std::cout;
using std::cin;
using std::endl;
缺省参数
using namespace std;
void Function1(int a=10;int b=20,int c=30)
{
cout:"a="<<a<<endl;
cout:"b="<<b<<endl;
cout:"c="<<c<<endl;
}
int main()
{
Function();
Function(1);
Function(1,2);
Function(1,2,3);
//Function(,2,3);缺省参数不支持跳跃传参
}
上述为全缺省情况
void Function1(int a;int b=10;int c=30)
//半缺省情况,且缺省值只能从右往左给,必须连续给,否则不能区分赋值情况
//void Function(int a=10;int b;int c=30)
//Function(10,20)无法知道10是赋值给a或者b
缺省值的声明和定义不能同时给,会导致重定义问题,只能在声明时给缺省参数赋值 (定义时给会导致包含声明的头文件被包含时,无法看出缺省参数的赋值)
函数重载
函数名相同,参数不同(类型不同,个数不同,顺序不同 )返回值可同可不同
void fun()
{}
void fun(int a=0)
{}
int main()
{
fun();//构成函数重载,但是会产生二义性产生错误
}
返回值不同不参与重载规则,调用时并不涉及返回值,无法具体调用
预处理(头文件展开,去注释,宏替换,条件编译)-》编译连(语法,生成汇编代码)-》汇编(转换为二进制机器码)-》连接(合并到一起,连接一些没有确定函数地址等)
函数名修饰规则 :存在同名函数,这些函数在编译时寻找为了区分有函数名修饰,参数不同修饰出的函数名不同,用该函数名确定连接的函数地址
引用:
引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。
引用必须实体化,有赋值对象,不能单独定义,一个对象可以有多个别名,但是多个对象不能有一个别名(重定义),即没有多级引用
int main()
{
int a=0;
int& c=a;
int b=1;
c=b;//这里是b的值赋值给c(也就是a。两者指向同一个区间),不改变指向,所以不能代替指针
}
引用作为函数参数时可以作为优化,避免传值拷贝
引用作为函数返回值时若是函数中局部变量的返回则可能为随机值。
常引用
int main()
{
const int a=10;
//int& b=a;权限不能放大,常变量a不能在引用b上得到修改的权限
const int& b=a;
int c=20;
const int& d=c;//权限可以缩小
const int& e=10;//可行,常属性不变
//int& f=10 不可行,权限放大
int i=1;
double j=i;
//double rj=i;不可行
const double rj=i;//可行,i在隐式类型转换时的临时变量具有常属性
char ch='x';
char& rch=ch;//语法上,rch并没有开空间
char* rrch=&ch;//定义的指针变量开了空间
cout<<sizeof(rch)<<endl;//大小为1,为ch的大小
cout<<sizeof(rrch)<<endl;//大小为8
return 0;
}
引用和指针的不同点:
- 引用概念上定义一个变量的别名,指针存储一个变量地址。
- 引用在定义时必须初始化,指针没有要求
- 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何
一个同类型实体 - 没有NULL引用,但有NULL指针
- 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32
位平台下占4个字节) - 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
- 有多级指针,但是没有多级引用
- 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
- 引用比指针使用起来相对更安全
内联函数
C中宏优点:不用建立栈帧,提高效率,,缺点,没有常量检查,单纯的替换会造成语法错误。
C++中使用枚举(enum)与内联函数(inline)代替宏 ,同样具有宏的优点并加以检查缺点
enum const inline代替宏
enum const 代替宏常量
inline 代替宏函数
inline int add(int x,int y)
{
int c=x+y;
return c;
}
int main()
{
int ret=add(1,2);
return 0;
}
VS的默认设置下Debug下会将内联函数作为普通函数展开,Releas下优化后则不会建立栈帧而是逻辑上在调用处展开
编译器并不一定会将内联函数展开,太长的内联函数(一般>10行)编译器不会展开,递归函数也不展开
内联函数的声明和定义不能分离(出现无法解析错误),因为内联函数可以认为是不生成地址的
auto关键字
:自动推导类型 (右值已有确定的类型)
typeid(变量名).name() 打印变量名
省略类型的定义
vertor<string> v;
vertor<string>::iterator it=v.begin();//-》
auto it = v.begin();
auto 不能作为函数参数,函数返回值
范围for循环
依次取该范围中的值赋值给(拷贝)a,自动判断,自动结束
char arr[]={1,2,3,4};
for(auto a:arr)
{
cout<<a<<endl;
}