新的改变
学过了C语言, 在写代码的时候经常在C程序中看到C++的影子, 尝试浅尝一下C++的强大. 本文特色能使用图片就不用文字, 使用最通俗的语言, 最简单的语言来记录, 为日后的复习有个轻松愉快的体验.
C++程序的内存模型
分为四个区: 代码区, 全局区, 栈区, 堆区.
常量这里回顾一个概念: 指针常量(* const)与常量指针(const *), 就近原则, const后面是什么, 什么就不能改, 如" *p代表指针指向的值 ", " p代表指针变量 ".
const修饰的是常变量, 本质上还是变量.
new与delete关键字
new在堆上开辟一个空间, 返回该空间的地址.
int *p = new int(10); //开辟一个int类型的空间, 里面放上10
delet p; //释放
int *p = new int[10]; //创建10个int类型的空间
delet p[]; //释放数组
引用
变量别名
作用: 给变量起别名, 简化指针的操作.
int a = 10;
int& b = a;
cout << "a的地址是" << &a << endl; //地址是000000BDE5EFF884
cout << "b的地址是" << &b << endl; //地址是000000BDE5EFF884
注意: ①引用必须要初始化. ②引用一旦初始化就不能修改(等同于const *类型的常量指针)
引用做函数的形参
void func(int &a)
{
a = 10;
}
int main(void)
{
int b = 100;
func(b); //改变了b的值 b = 10;
}
这个逻辑为实参为b, 传入的参数为b的地址, 然后改了一个别名叫做a, 实际a与b的地址均为同一个, 因此可以修改.
引用做函数的返回值
//错误代码
int & test(void)
{
int a = 10;
return a;
}
//正确代码
int & test(void)
{
static int a = 10;
return a;
}
int &temp = test();
在栈区上的局部变量出了函数就会被销毁, 但是却把销毁的地址传了回去, 造成了越界访问. 但是如果是static变量, 延长了生命周期, 将没有问题. 如果不想使用static关键字操作变量的话, 可以使用下面的这个方法, 在堆上开辟一个空间.
//配合new使用
int& test7()
{
int* p = new int(10);
cout << "地址是" << p << endl; //地址是000001882D166C90
return *p;
}
int main(void)
{
int& a = test7();
cout << "地址是" << &a << endl;//地址是000001882D166C90
cout << "内容是" << a << endl;//内容是10
delete& a; //销毁
return 0;
}
函数的局部变量虽然看着像是指针丢失了, 其实引用已经将地址返回来了, 不会造成内存泄漏问题. 但是要手动销毁, 日后可以搭配析构函数来使用.
//稀奇古怪的写法, 函数引用做左值
int & test(void)
{
static int a = 10;
return a;
}
int main(void)
{
//1
test() = 100;
//2
int& a = test8();
test8() = 1000;
}
第一种写法没错, 但是注意静态变量a此时的值为100;
第二种写法是修改了静态变量a = 1000;
const修饰引用且赋值常数
int& a = 10; //非法访问
const int& a = 10; //正确
理解: 系统会开辟一个空间, 使用别名访问, 这个空间只读且里面的内容为10.(实际没什么用)
使用案例: 当做函数的形参使用, 防止误操作.
函数的默认参数与占位参数
规则与规范
- 函数的声明和定义只能有一个有默认参数.
- 默认参数最好是声明时候给出默认参数, 方便调用者查阅.
- 占位参数也要传参.
- 占位参数也可以有默认值.
int temp(int a, int b = 10);//默认参数
temp(1,2); temp(1); //调用
int temp(int a, int);//占位参数, 就是还没想好要不要加, 先加上.
temp(1,2);//调用
temp(1); //错误
int temp(int a, int = 10); //占位参数带有默认值
temp(1,2); temp(1); //调用
函数的重载
目的: 函数名可以相同, 通过一个函数名实现对多种输入数据进行处理, 提高复用性.
规则:
----① 函数名相同, 返回值相同.
----② 在同一个作用域下.
----③ 参数不同, 参数类型/个数/顺序, 要保证至少有一个不相同.
----④ 带有默认值的参数, 要保证和其他函数调用时没有歧义.
注意: 返回值不能作为函数重载, 调用时会造成歧义.
参数为引用
//可以构成重载
void fun(int & a);
void fun(const int & a);
//调用
int a = 10;
fun(a); //调用第一个
fun(10); //调用第二个, 如果没有第二个将会报错
分析: 还记的上面学的引用吗, int &a = 10是非法的, 非法访问, 而const int & a = 10; 是正确的.