C++基础
函数重载
能够使用多个同名的函数,完成相同的工作,但使用不停的参数列表。
形象的理解,就是同一句话,有着不同的含义,在c++要根据上下文来确定其意思。
其主要的核心是特征标 ==参数数目/参数类型/参数顺序==
返回值没有特别的要求。
问题:C++是如何支持函数重载的?为什么C语言不支持函数重载呢?
主要符号表中表示歧义,函数命名c语言是以函数名来储存的,而C++是函数名+参数类型,同时链接的时候也存在冲突
list.h list.c test.c
代码处理的过程
1.预处理 头文件展开,宏替换,条件编译,去掉注释
list.i test.i
2.编译 检查语法,生成汇编代码
list.s test.s
3.汇编 汇编代码转为二进制机器代码
list.o test.o
4.连接 将多个个目标文件链接到一起
引用变量
引用变量时必须同时进行初始化,引用取别名时,变量访问的权限可以缩小,不能放大
例:
int c=1;
int &d=c;
const int &e=c; //c是可读可写的,而e变成别名只读
int a=10;
double db=i; //隐士类型转化
double & c=a; //error
const double &c=a; // right
//变量赋值没有权限的放大和缩小之分,引用才有用
引用返回值
#include<iostream>
int& add(int a, int b)
{
static int c = a + b;
return c;
}
int main()
{
using namespace std;
int& ret = add(1, 2);
add(3, 4);
cout << ret << endl;
总结:一个函数要使用引用返回值,返回变量出了这个函数的作用域还存在,就可以使用这个返回,否则就不安全。
使用引用返回的好处,少拷贝一个临时变量,提高程序效率
1.引用做参数
a.输出型参数
b.提高效率
2.引用做返回值
a.提高效率
b.后期补
指针和引用的区别
int a;
int& b=a;
int* p=&a;
引用是a的别名,语法上不开辟空间,在底层的应用中,实则是用指针来开辟空间
不同点:
1.引用在概念上定义一个变量的别名,指针存储一个变量的地址
2.引用在定义的时候必须初始化,指针没有这样的要求,但最好将指针设为空(NULL)
3.引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型的实体
4.没有NULL引用,但有NULL指针
5.在sizeof中含义不同,引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(在32位操作系统下是4个字节)
6.引用自加即引用的实体加一,指针自加即指针向后偏移一个类型的大小
7.有多级指针,但是没有多级引用
8.访问实体方式不同,指针需要显示解引用,引用编译器自己处理
9.引用比指针使用起来相对安全
内联函数
inline修饰的函数成为内联函数,编译时c++编译器会在调用内联函数的地方展开。
频繁调用函数是有消耗的,会建立栈帧
如何解决?
1.c语言使用宏函数
2.c++使用内联函数
内联函数在release模式下会进行展开,在debug模式下不会进行展开,需要对编译器进行设计,否则代码不会对其进行优化。
空间换时间。
后期补一下release和debug模式的区别。
1.一般内联适用于小函数,小于20行,其他的例如递归,或者比较长的都不太适用于内联
2.inline对于编译器而言只是一个建议,编译器会自动进行优化
3.内联是不能定义和声明分离的。
内联与宏
宏的优缺点:
优点:
1.增强代码的复用性
2.提高性能
缺点:
1.不方便调试宏。why?预编译的阶段进行了替换
2.导致了代码的可读性差,可维护性差,并且容易误用
3.没有类型安全的检查。
c++中替代宏的操作
#define N 10
const int N = 10;
宏函数替换为内联函数。
auto关键字(C++11)
自动推导变量
#include<iostream>
int main()
{
int a=0;
auto b=a; //根据a推导b的类型
auto& c=a;
auto d =&a;
}
C++中看一个变量的类型的操作:
count<<typeid(变量).name()<<endl;
注意当auto同一行多个变量时,得需是同一种类型的
auto不能推导的场景:
1.auto不能作为函数的参数
//不能作为形参类型,无法具体推导
void add(auto a);
2.不能直接用来声明数组
int a[10]={ };
auto b[ 10]={ }
3.避免c++98中的auto的混乱。c++11只保留了auto作为类型指示符的用法
4.后面讲到的c++11for还有一些表达式的用法。map的用法。简化代码得写法。
基于C++11范围for的用法
举个例子
//将数组中的值乘以2倍
//C语言的做法
#include<iostream>
int main()
{
int arry[]={1,2,3,4,5};
for(i=0;i<sizeof(arry)/ssizeof(int);i++)
{
arry[i]*=2;
}
for(i=0;i<sizeof(arry)/sizeof(int);i++)
{
count<<arry[i]<<" ";
}
count<<endl;
}
//用for的用法 语法糖,写代码会进行简介点
for(auto& e : arry)
{
e*=2;
}
for(auto e : arry)
{
count<<e<<" ";
}
count<<endl;
基于范围for的操作对象是数组,
范围for的使用条件
1.for循环迭代的范围必须是确定的
对数组的而言,就是数组第一个元素和最后一个元素的范围
C++中的空指针的表达形式
c语言中一般表达空指针的形式为NULL,而C++中推荐的表达形式为nullptr->空指针。
NULL其实是一个宏定义,在C语言中,被定义为0,或者被定义为无类型指针(void*)的常量。
CONST修饰指针
const Date* p1; //*p1,指向的对象
Date const * p2; //*p2,指向的对象
Date* const p3; //->p3,指向本身
//*之前的都是对象,*之后的是指针本身