1.C++学习知识点汇总
:命名空间,输入输出,缺省函数,函数重载(C++为什么支持重载?),引用(const权限的问题,static的作用),内联函数,auto关键字,范围for,C++11.
2.命名空间的使用有三种方式:
//1.加命名空间名称机作用域限定符
int main()
{
int a;
printf("%d\n",N::a);
return 0;
}
//2.使用using将命名空间中成员引入
using N::b;
int main()
{
int a,b;
printf("%d\n",N::a);
printf("%d\n",b);
return 0;
}
//3.使用using namespace 命名空间名称引入
using namespace N;
int main()
{
int a,b
printf("%d\n",a);
printf("%d\n",b);
return 0;
}
3.C++输入与输出:
cout<<输入流;cin>>输入流;endl:换行,也可以用\n;
4.缺省参数:
1.半缺省(缺省部分参数):必须从右往左连续缺省
2.缺省参数不能在函数声明和定义中同时出现
3.缺省值必须是常量或者全局变量
4.C语言不支持
//缺省参数
void Func(int a=0)
{
cout<<a<<endl;}
int main()
{
Func(10);//a=10;
Func(); //a=0;
return 0;
}
//半缺省:(缺省部分参数)必须是从右到左连续缺省
void Func2(int a,int b=20,int c=30)
{
cout << "a=" << a << endl;
cout << "b=" << b << endl;
cout << "c=" << c << endl;
}
int main()
{
Func2(1); //a=1,b=20,c=30;
Func2(1,2); //a=1,b=2,c=30;
Func2(1,2,3);//a=1,b=2,c=3;
return 0;
}
//全缺省
void Func3(int a=10,int b=20,int c=30)
{
cout << "a=" << a << endl;
cout << "b=" << b << endl;
cout << "c=" << c << endl;
}
int main()
{
Func3(); //a=10,b=20,c=30;
Func3(1); //a=1,b=20,c=30;
Func3(1,2); //a=1,b=2,c=30;
Func3(1,2,3);//a=1,b=2,c=3;
return 0;
}
5.函数重载:函数重载是函数的一种特殊情况,C++允许在同一作用域中声明几个功能 类似的同名函数,这些同名函数的形参列表(参数个数或类型或类型序序 必须不同)常用来处理实现功能类似数据类型不同的问题。
1.符号表的名称:—Z+函数名的长度+函数名+参数类型;
//类型不同
int Add(int left, int right)
{
return left + right;
}
double Add(double left, double right)
{
return left + right;
}
long Add(long left, long right)
{
return left + right;
}
//顺序不同
void Hunc1(int i, char ch)
{
}
void Hunc1(char ch,int i)
{
}
//只是返回值不同,不能构成重载
void Hunc1()//0个也构成重载
{}
2.函数调用重载时,会自动进行类型识别
int main()
{
//函数重载调用时,会进行类型识别
Add(10, 20);
Add(10.0, 20.0);
Add(10L, 20L);
Hunc1();
Hunc1('a', 10);
Hunc1(11, 'b');
return 0;
}
重载:面试问题:1.什么的重载?2.C++是如何支持重载的,为什么C不支持?
答:1.函数重载的定义;
2.
3. extern ”C“ :按C语言的修饰规则去找。
6.引用:引用不是新定义一个变量,而是给已存在变量取一个别名 编译器不会为引用变量开辟内存空间,它和它引用的变量共用一块内存空间 比如:李逵,在家被称为”铁牛“,江湖上人称”黑旋风“。
1.类型&引用变量名(对象名)=引用实体; 2.引用必须在定义的时候初始化;一个变量可以有多个引用
int a=1;
int& ra=a;//ra是a的引用,引用也就是别名,a再取了一个名称ra
int& b=a;//1.引用必须在定义的时候初始化
int& c=b;//2.一个变量可以有多个引用
c=10;
int a=1;int& c=a; int b=2; c=b; 分析:这里是c变成了b的引用,还是将d赋值给c? 答:是将d赋值给c.
3.const权限的放大和缩小,放大是错误的,可读可写和只读的类型转换,赋值不考虑,引用和指针存在该规则
int a=1,int& b=a;//b的类型还是int
const int a=0;int& b=a//编译不通过,原因:a是只读,b的类型是int,也就是可读可写的,所以不行
const int a=0;const int& b=a;//这样可以,两者都只是可读的
int c=1;int& d=c;const int& e=c;//行不行?可以,c是可读可写的,e变成别名只读
总结:引用取别名时,变量访问权限可以缩小,不能放大
int i=0;const double& db=i; const float& rdb=i;
int i=0; double db=i;//隐式类型转换:int i赋值给double类型的d时会在中间产生一个临时变量
//临时变量具有常性,常性可以认为是const
const double& rd=i; const float& rf=i;//这两个表达式也是在中间产生了一个临时变量,从可读可写转换
//为可读
const int ci=i; int x=ci;//变量赋值没有权限缩小和放大的关系,引用才有
const int a=10; int& b=a;//权限放大,不能把const给非const 这种语句是错误的
int c=20;int& b=c; const int& e=c;//权限缩小,非const即可以给非const也可以给const
指针:
const int*cp1=&a;int*p1=cp1;//错误的,属于权限的放大
int*p2=&c; const int*cp2=p2;//可以,属于权限的缩小
权限放大和缩小的规则:适用与引用和指针间。
4.引用做参数:
//r1,r2在传值的时候初始化
void swap_cpp(int& r1,int& r2)
{
int tmp=r1;
r1=r2;
r2=tmp;
}
int main()
{
int a=0,intb=1;
swap_cpp(a,b);
return 0;
}
5.引用做返回值
//传值返回
int Count1()
{
static int n=0;//static修饰生命周期
n++;
return n://返回的时候,会创建一个临时变量tmp,把n的值赋给tmp,int tmp=n;tmp的类型就是函数的类
型int,因为是临时变量,所以具有常性,const,只能读,所以要用const类型变量接收
}
int main()
{
const int& r1=Count1();
return 0;
}
6.传引用返回
//传引用返回
int& Count2()
{
static int n=0;
n++;
return n;//返回的时候,对n进行引用,int& tmp=n,并没有创建新的空间,tmp只是n的别名,
//相当于返回n
}
int main()
{
int& r2=Count2();
return 0;
}
7.static的作用:延长变量的生命周期,使变量在静态区不会被销毁
int& Add2(int a,int b)
{
int c=a+b;
return c;
}
int main()
{
int& ret=Add2(1,2)//ret是c的别名
Add2(3,4);
cout<<"Add2(1,2)is:"<<ret<<endl;//输出为7
return 0;
}
//思考为什么ret为7?
答:因为main和Add2的变量都存储在栈里,执行完第一个Add2时,变量就被销毁了,所以ret等于第2个Add2的值,说明如果返回变量C是一个局部变量时,引用返回是不安全的,只要在C前加一个static,C变量就在静态区,
不会被销毁。
总结:一个函数要使用引用返回,返回变量出了这个函数的作用域还存在,就可以使用引用返 回,否则不安全。
那么函数使用引用返回好处是什么呢?->少创建拷贝一个临时对象,提高效率,还有一个后面讲
全局变量,静态变量等可以引用。
引用和指针的区别:
1.int a=10,int&b=a,int* p=&a;语法概念上:b就是a的别名,指针存储一个变量的地址
2.引用在定义时必须初始化,指针没有要求
3.引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时刻指向任何一个同类型实体
4.没有NULL引用,但有NULL指针
5.在sizeof中含义不同,引用结果为引用类型的大小,但指针占4个字节(32位机器)
6.引用自加即引用的实体增加1,指针自加即后偏移一个类型的大小
7.有多级指针,没有多级引用
8.访问实体方式不同,指针需要显示解引用,引用编译器自己处理
9.引用比指针使用起来相对更安全
7.内联函数 :(空间换时间)以inline修饰的函数叫内联函数,编译时c++编译器会在调用内联函数的地方展开,展开成多条指令
inline void swap(int*p1,int*p2)
{
int tmp=*p1;
*p1=*p2;
*p2=tmp;
}
int main()
{
int a=0,b=2;
swap(&a,&b);
return 0;
}
频繁调用函数需要建立栈帧,是有消耗的,应该如何解决呢?
C语言用宏函数,C++用内联函数解决
一般内联适用于小函数(小于20行),其次是递归,或者比较长的都不适宜内联
8.auto关键字(C++11)
8.auto
int main()
{
int a = 0;
auto b = a;//b的类型根据a的类型推导出是int
int& c = a;
auto& d = a;
auto* e = &a;
auto f= &a;
cout << typeid(a).name() << endl;//int
cout << typeid(b).name() << endl;//int
cout << typeid(c).name() << endl;//int
cout << typeid(d).name() << endl;//int
cout << typeid(e).name() << endl;//int*
cout << typeid(f).name() << endl;//int*
return 0;
}
auto不能推导的场景
1.auto不能作为函数的参数
void TestAuto(auto a)
{}
2.auto不能直接用来声明数组
3.这里不能用,因为arrary不是数组,是指针
void TestFor(int arrary[])
{
for(auto & e: arrary)
{
cout<<e<<" ";
}
}
9.范围for(C++11)
void TestFor(int arrary[])
{
for (auto& e : arrary)//不能使用,因为arrary已经不再是数组,而是指针
{
cout << e << endl;
}
}
int main()
{
int arrary[] = { 1,2,3,4,5,6,7,8,9, };
//要求将数组中的值乘2,并打印出来
for (int i = 0; i < sizeof(arrary) / sizeof(arrary[0]); i++)
{
arrary[i] *= 2;
}
for (int i = 0; i < sizeof(arrary) / sizeof(arrary[0]); i++)
{
cout << arrary[i] << "";
}
cout << endl;
//C++11->范围for->特点:写起来简洁
for (auto& e : arrary)
{
e*= 2;
}
for (auto& e : arrary)
{
cout << e << "";
}
cout << endl;
}
10.C++11中空指针推荐用nullptr
int main()
{
fun(0);
fun(null);//预处理后fun(0)
fun(nullptr);//fun((void*)0);
retyrn 0;
}