2.1掌握对对象的优化
- 不能返回局部的或者临时对象的指针和引用 — 在退出局部变量环境时,局部变量就会退出栈,此时你的指针和引用就会指向一块脏内存
- 在函数里面返回临时对象的时候,返回类型不能是指针或者引用 — 与上面同理
- 函数调用,实参=》形参, 是一个初始化的过程
2.2inline 内联函数与普通函数的区别
inline内联函数,在编译过程中就没有函数调用的开销了,在函数调用点直接把函数的代码进行展开处理
#include<iostream>
using namespace std;
inline int sum(int a = 10, int b = 20)
{
int temp = 0;
temp = a + b;
return temp;
}
int main()
{
int a = 10;
int b = 20;
int ret = a + b;
cout << "ret:" << ret << endl;
return 0;
}
inline函数不再生成相应的函数符号
可以省下函数调用的开销
也不会生成相应的函数符号
但不是所有inline都会被编译器处理成内联函数 – 递归
inline只是对编译器的建议
debug版本上inline是不起作用的,不然没办法debug
2.3 详解函数重载
示例代码:
#include<iostream>
using namespace std;
bool compare(int a, int b)
{
cout << "copare_int_int" << endl;
return a > b;
}
bool compare(double a, double b)
{
cout << "compare_double_double" << endl;
return a > b;
}
bool compare(const char* a,const char* b)//为了表明这个函数不会修改传入的字符指针所指向的内容。
{
cout << "compare_char * _char *" << endl;
return strcmp(a, b) > 0;
}
int main()
{
compare(10, 20);
compare(10.0, 20.0);
compare("aab", "ccd");
return 0;
}
问题1:为什么c++支持函数重载,而c不支持?
答1:c++代码在产生函数符号的时候,是函数名+参数列表类型组成的!
而c代码产生函数符号的时候,函数名来决定。
也就是说在c中,因为函数名相同,会发生链接错误。
问题2:函数重载需要注意什么?
示例代码:
int main()
{
bool compare(int a, int b);//函数的声明
compare(10, 20);
compare(10.0, 20.0);//警告double->int有可能出错
compare("aab", "ccd");//错误char不能转为int
return 0;
}
答2:实际上就是作用域的问题,只有在同一个作用域内的相同函数名直接使用不同的参数列表才能进行重载。
问题3:const和volatile是怎么影响形参类型的
void func(int a){};
void func(const int a){};
int main()
{
return 0;
}//错误
答3:在编译器眼中,这两种都是int类型,只是权限不同,所有不能重载。
问题4:请你解释一下什么叫多态?
答:分为静态的多态和动态的多态
静态的多态(编译时期的多态):函数重载
什么是函数重载:从函数调用来看,是处在同一作用域内的同名但不同参数列表的一组函数。
动态的多态(运行时期的多态):
问题5:
c++调用c代码
由于c++和c生产符号的规则不一样,所以在编译的时候,无法进行对应(找不到)。
解决方法:
在外部加上
extern "C"
{
函数声明
}
c调用c++代码
由于C不认识
extern “C++”
{
函数声明
}
这个操作,所以不能直接反过来用
怎么办呢?把c++源码扩在extern“c”里面
2.4 全面掌握const
- const修饰的变量不能作为左值 — 初始化完成后,不能被修改。
- c和c++中const的区别:
同一段代码
#include<iostream>
//#include<stdio.h>
using namespace std;
int main()
{
const int a = 10;
int* p = (int*)&a;
*p = 30;
printf("%d %d %d",a , *p , *(&a));
}
在c中的结果为,30 ,30 ,30
在c++中的结果为,10 ,30 ,10
在C中,const就是当作一个变量来编译生成指令的。
在C++中,所有出现const常量名字的地方,都被常量初始化替换了
所以在C++中第一个结果和第三个结果都是被常量初始化替换了,就是初始化的10,而实际上a的值也已经被*p给修改了
- const修饰的量,可以不用初始化,不叫常量,叫做常变量
2.4.1 const和一级指针的应用
const修饰的值在c++叫做常量
与普通变量的区别:
- 编译方式不同
- 不能作为左值 (直接修改)
- 不能把常量的地址泄露给普通的指针或者普通的引用变量 (间接修改)
const修饰的是离他最近的类型
const int *p= &a; =》 *p = 20 不行 =》 p = &b 可以
可以任意指向不同的int类型的内存,但是不能通过指针间接修改指向的内存的值
此时const修饰的是int
int const *p; =》 其实和上面的是一样的
因为const不能只修饰*,所以修饰的是int
int *const p = &a; =》 *p = 20 可以 =》 p = &b 不行
为const不能只修饰*,所以修饰的是int*,是指针
所以此时p不能指向其他内存,但是内存指向的值可以修改
指针是常量
const int *const p;
此时就是上两种情况的结合,即都不能修改
总结const和指针的类型转换公式
int* 《= const int * 是不行的
const int * 《= int* 是可以的
2.4.2 const和二级指针的应用
int main()
{
int a = 10;
int *p = &a; // int *《= int * 可以
const int **q = &p; // const int* <= int * 可以
}
类型总结
判断题总结:
A.
int a = 10;
const int *p = &a;// const int * 《= int * 可以
int* q = p;// int * 《=const int * 不行
所以是错的
B.
int a = 10;
int *const p = &a;// int * 《= int * 可以
int* q = p; // int * 《= int * 可以
所以是对的
C
int a = 10;
int *const p = &a; //int * 《= int * 可以
int *const q = p; // int * 《= int * 可以
所以是对的
D
int a = 10;
int *const p = &a;// int * 《= int * 可以
const int *q = p; // const int* 《= int* 可以
所以是对的
E
int a = 10;
int *p = &a;
const int **q = p;// *q就是p,那么**q就是*p
//因为q指向的是const int类型的指针,而p指向的是一个普通的int类型变量
所以是错的
F
int a = 10;
int *p = &a;
int *const*q = &p;//const* 《= * 可以
所以是对的
2.5 引用与指针
引用是一种更安全的指针
- 引用必须初始化,指针可以不用初始化
可以看到,定义一个指针和定义一个引用在汇编指令层面是一样的操作
通过指针和引用在汇编指令层面修改值的操作也是一样的
左值引用和右值引用
左值引用:有内存,有名字,值可以修改
int &c = 20;错误
//20是右值,没内存。没名字
右值引用:
int &&c = 20;可以
这一段没看懂——以后再补吧
2.6 new和delete
new和malloc的区别是什么?
delete和free的区别是什么?
- malloc和free是c的库函数
new和delete是运算符
#include<iostream>
int main()
{
int* p = (int*)malloc(sizeof(int));
if (p == nullptr)
{
return -1;
}
*p = 20;
free(p);
//相对于的new操作
try{
int* p1 = new int(20);
}
catch (const bad_alloc &e)
{
}
return 0;
}
delete p1;
new 不仅可以开辟内存,还可以做内存初始化操作
而malloc只开辟内存
-
malloc开辟内存失败是通过返回值和nullptr做比较的;而new开辟内存失败是通过抛出bad_alloc类型的异常来判断的。
-
开辟数组内存时:
int main()
{
int* p = (int*)malloc(sizeof(int)*20);
if (p == nullptr)
{
return -1;
}
*p = 20;
free(p);
//相对于的new操作
int* p1 = new int[20];//中括号
//int* p1 = new int[20]()
//如果加一个()就表示把数组初始化为0
return 0;
}
- new有多少种?
int *p1 = new int(20);
int *p2 = new (nothrow) int; 不抛出异常版
const int *p3 = new const int(40);
//定位new
int data = 0;
int *p4 = new (&data) int(50);
在指定的地址(&data)开辟一个int内存 并且赋值为50