学习目标:
持之以恒,方能成功!!!
- 一周掌握 c++入门知识
学习内容:
首先需要了解的则是C语言和c++的关系:
1.c++是一个独立的语言和C语言是出于一种并列的关系
2.c++兼容C语言,c++中可以输入C语言代码
3.C语言是面向过程的(瀑布式),c++是面向对象编程(并列式)
4.c++23标注向下兼容(也就是23年之前的都可以实现)。c++11是标准。
5.头文件不同:C语言后缀都有.h,而c++则是没有.h,并且在前面加上c
6.对于linux来说编译C语言使用gcc进行编译,而对于c++来说编译使用g++进行编译
7.c++编译的源文件的后缀是.cpp,而C语言则是.c
8.输入、输出也不一样,c语言是scanf printf c++ cout cin 流的方式
- c++中对于函数的引用
1)定义: 给变量取别名,不占用内存空间,和别名同生死。
2)语法:数据类型 &别名 = 原名;
引用:int& p = x; 指针: int* p = &x;
3)使用场景: 函数参数
#include<iostream>
using namespace std;
int fun(int& x,int& y)
{
int t=x;
x=y;
y=t;
cout<<"函数内部x="<<x<<"y="<<y<<endl;
}
int& add(int a,int b)
{
static int temp=10;
return temp;
}
int main()
{
int a=10;
int b=20;
int& y=a;
y++;
y=b;
fun(a,b);
cout<<"a="<<a<<"b="<<b<<endl;
int& t=add(1,2);
cout<<"temp="<<t<<endl;
return 0;
}
4)引用的要求:
A:引用必须初始化;
B: 引用一旦初始化则不可以修改
5)引用当做函数参数和返回值
int fun(int& x, int& y)
int& add(int a,int b){ } 需要注意 返回的引用不可以是普通局部变量
2.输入和输出
1)输入:cin
语法:cin >> 变量 ; 变量不需要取地址符号
cin >> 变量 >> 变量 同时输入多个变量
cin >>“请输入” >> 变量 错误的,不可以使用
2)输出:cout
头 文 件: iostream
名字空间: using namespace std;
使 用: cout << “hello”; 直接放字符串,原封不动打印
cout << x ; 直接打印变量的值,没有占位符
cout << “x=” << x; 流运算符可以连续使用
3)换行: endl
使用: 遇到endl 则换行; cout中可以有多个endl 可以放中间 可以放末尾
endl和“\n”是等价的。只是”\n”是字符串;
案例:请输入学生信息,打印信息 (id age)
3.标准错误流和标准日志流
1)标准错误流
定义:iostream中,定义了一个对象cerr ,用来打印错误信息,没有缓存,立即输出
使用: cerr << 字符串<< 变量 和cout的使用一样的;
案例: cerr << "我是错误"<< danny.age <<endl;
2)标准日志流
定义:iostream中的对象clog,通常用来显示信息,有缓存。
使用: clog << “字符串” << endl; 也和cout一样。
3)输入输出的格式化处理
cout.width(10); 设置输出的宽度是10个字符;
cout << setiosflag(ios::left);
setiosflags(ios::left) 左对齐
setiosflags(ios::right) 右对齐
4.名字(命名)空间
1) 引入:为了解决同名的冲突,名字污染。模块化的代码,高内聚低耦合。
2) 定义: namespace 名称{内容}
3) 可以定义: 函数,变量,结构体,另外名字空间,枚举联合都可以;
4)名字空间的使用
A:使用using 指令
全部引入:using namespace 名字空间名;接下来所有的变量都是名字空间中的;
using namespace danny;
部分引入:using 名字空间名::变量/函数 ; 接下来的变量都是名字空间中的;
using danny::b;
B:使用域调用
域调用: 名字空间::变量/函数
案例: strcpy(danny::name,"danny");
5)名字空间的嵌套
定义:在名字空间中定义另外一个名字空间,叫做名字空间嵌套
使用: using namespace 外名字空间:: 内名字空间;
外名字空间::内名字空间::变量;
using 外名字空间::内名字空间::内名字空间变量
6)相同名字空间:
如果定义了相同的名字空间,会自动合并,如果有相同的变量名则会冲突
7)名字空间命别名
namespace 别名= 名字空间名;
5.内联
1)内联作用
在c语言中,如果有函数频繁调用,需要入栈出栈等复杂操作,效率不高。
为了解决效率问题,有了内联函数,关键字是inline;
内联函数一般和类一起使用,如果一个函数定义成内联,则在编译的时候;
会把该内联函数用代码副本替换。函数调用位置会用函数体替换。
2)定义内联
在函数前加上inline关键字
在类中,内部定义的函数都是内联函数。
3)注意事项
A:内联函数不允许使用循环和switch
B:不可以超过10行,超过后则不会定义成内联。
C:调用之前需要先定义
D:如果已经定义了inline,但不符合内联的要求,编译器会自动忽略inline限定。
4)优缺点
当函数体比较小的时候,内联函数可以达到比较高的运行效率
内联函数不需要创建栈和销毁栈的过程,不需要保护现场。
缺点:复杂的函数无法使用内联,inline的要求比较多;
6.函数重载
1)定义:c++允许同一个函数名定义的多个函数,这些函数的参数不同。则构成重载;
在同一个作用域内,函数名相同参数列表不同的多个函数
2)参数列表不同
参数个数不同,参数顺序不同,参数类型不同
案例:请写一类函数,可以计算两个数,三个数,四个数五个数的和;
3)目的
前人种树后人乘凉:减少了用户使用函数的复杂性,调用一个函数实现多个效果
减少了函数名字污染,有利于程序的可读性
4)实现原理
先objdump -d a.out > danny.log 产生反汇编代码
编译器在编译的时候,把相同的函数名进行的取别名,
案例:int add(int a,int b) ---> -z3addii
规则:_z3是返回值类型,i表示一个int,Ss表示字符串string类型,c表示char类型
l表示long类型,大部分使用的是类型的首字母。
5)按照c语言的规则编译
在函数前加上extern “C” ,则在c++编译中,按照c语言的规则编译
也就是在编译后不会修改函数名;
如果多个函数都需要按照c语言规则 则用括号
例如: extern “C” { XXXXX }
7.重载的匹配
精准匹配: 参数不做任何转换就可以找到对应的函数,实参和形参类型个数都相同
提升匹配: 类型做提升(bool->int,char提升到int,short提升到int,float提升到double
转换匹配: int-->double, double->int, int -->unsigned int
省略匹配: 可变长参数的匹配。
8.注意事项:
A:在类中,const函数和非const函数构成重载(参数列表相同也构成重载)
B:在函数参数中,const参数和非const参数不构成重载
C:一定是在同一个作用域内,不可以在多个作用域
D:函数名必须相同,不相同不构成重载,是多个函数。
9.缺省参数
定义:当函数调用过程中,不传入参数,则会使用默认值。
案例: int add(int a = 10){ cout << “abc”<<endl;}
注意: 函数调用时,如果对应参数传入了实参则形参是实参的拷贝值;
如果没有传入实参,则会使用缺省值;
函数形参的缺省只可以从右往左连续缺省。不可以从左往右后。
实参的传递是从左往右,不可以用逗号等方式把左侧的缺省,右侧不缺省。
函数缺省参数会导致函数重载的二义性,需要注意防止出现重载后的问题;
函数在声明的时候需要加缺省值,定义的时候不允许加
10.new运算符
定义:new是c++中申请堆空间的函数,new和malloc相似,是动态申请内存空间;
格式:类型* 指针变量= new 类型;
类型* 指针变量= new 类型(初始值);
类型* 指针变量= new 类型[数组大小];
内存释放: delete 指针变量名
delete[] 指针名 ;指针指向的是数组;申请加中括号释放则需要中括号
总结: new的释放是delete ,malloc的释放是free; (能量守恒)
区别: new申请的是对象,对象有内存空间,malloc申请的是内存空间;
New申请的内存需要delete释放,malloc的需要用free释放
New可以初始化内存空间,malloc申请的内存不会初始化,需要用bzero
new申请的内存空间不需要转换,malloc申请的内存是void*类型,需要转换
都是在堆区申请内存。