#include<iostream>
using namespace std;
/*截止71之后转为此笔记
* struct 结构体名称 {结构体}
①结构体数组 struct student stu[5]{
---输入信息
};
熟练写冒泡,循环交换
通讯录实操
*/
/*C++核心编程--面向对象
C++在执行的时候内存大致分为4区
代码区: 存放函数体的二进制代码,由操作系统管理 (程序运行前就有) 编译后生成exe可执行程序
全局区:存放全局变量和静态变量以及常量 (程序运行前就有) global全局 static静态 const常量 local本地局部
结束后数据由操作系统释放 【全局和静态变量放得很近,常量离得也不远,但局部变量地址离得远】 只要局部修饰的,局部常量仍在局部区,离全局区远
栈区:由编译器自动分配释放,存放函数的参数值,局部变量等
堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收
*/
int* func()
{
int a = 10;//局部变量,存放在栈区,栈区的数据在函数执行完后自动释放
return &a; //返回局部变量的地址 ,局部变量地址返回后就被释放
}
void testfunc() {
int * p = func(); //接受返回值
cout << *p << endl;//因为局部被释放,此处非法操作!!
cout << *p << endl;//第一次防止误操作仍10,第二次就不是了
}
int * func2() {
//利用new关键字 ,可以将数据开辟到堆区
//指针本质也是局部变量,放在栈上,指针保存的数据是放在堆区
//在堆区创建整型数据
//用new开辟空间会返回和数据类型一样的指针
int* p = new int(10);
return p;
}
void testfunc2() {
int* p = func2(); //接受返回值,堆区数据,由程序员管理,程序员手动释放才释放,如果想释放delete
cout << *p << endl;
cout << *p << endl;
cout << *p << endl;
cout << *p << endl;
delete p; //内存访问已经被释放,再次访问就是非法操作,会报错
cout << *p << endl;
}
int * func3() {//在堆区用new开辟数组
//创建10整型数据的数组,在堆区
int *arr = new int[10]; //10代表数组有10个元素
for (int i = 0; i < 10; i++) {
arr[i] = i + 100; //赋值100~109
}
for (int i = 0; i < 10; i++) {
cout << arr[i] << endl;
}
//释放数组堆区内存
//释放数组的时候,要加[]才可以
delete[] arr;
return 0;
}
/*2.引用的基本使用
作用: 给变量起别名
语法:数据类型 &别名 = 原名
//引用注意事项:
*引用必须初始化
*初始化后不可以改变
*/
void quote(){
int a = 10;
int &b = a;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
int c = 20;
b = c;//等号是赋值操作,而不是更改引用 ,a、b、c均为20
cout << "a = " << a << endl;// 20
cout << "b = " << b << endl;// 20
cout << "c = " << c << endl;// 20
}
/*引用做函数参数
作用: 函数传参时,可以利用英语的技术让形参修饰实参
优点:可以简化指针修改实参
*/
void swap1(int a,int b) {//值传递
int temp = a;
a = b;
b = temp;
cout << "swap1_a = " << a << endl;//形参交换
cout << "swap1_b = " << b << endl;
}
void testswap1() {
int a = 10;
int b = 20;
swap1(a,b);
cout << "a = " << a << endl;//值传递实参不交换
cout << "b = " << b << endl;
}
void swap2(int *a,int *b) {//地址传递 --指针去接地址
int temp = *a;
*a = *b;
*b = temp;
cout << "swap2_a = " << a << endl;//形参交换
cout << "swap2_b = " << b << endl;
}
void testswap2() {
int a = 10;
int b = 20;
swap2(&a, &b);//注意
cout << "a = " << a << endl;//实参交换
cout << "b = " << b << endl;
}
void swap3(int &a ,int &b) {//引用传递 引用给变量取别名
int temp = a;
a = b;
b = temp;
}
void testswap3() {
int a = 10;
int b = 20;
swap3(a, b);//取别名,也就是交换实参中的数据
cout << "a = " << a << endl;//实参交换
cout << "b = " << b << endl;
}
//引用做函数的返回值
//1.不要返回局部变量的引用!!
int& test1() {//返回a的引用 test1() == a的别名
int a = 10;//局部变量存放在四区中的 栈区
return a;
}
void test_test() {
int& ref = test1();
cout << ref << endl;//第一次结果正确,是因为编译器做了保留
cout << ref << endl;//第二次结果错误,因为a的内存已经释放
}
//2.函数的引用可以作为左值
int& test2() {
static int a = 10;//静态变量,存放在全局区,全局区上的数据在程序结束后系统释放
return a;
}
void test_test2() {
int& ref2 = test2();//&ref2 为a的别名
cout << "ref2 :" << ref2 << endl;//10
cout << "ref2 :" << ref2 << endl;
//--->如果函数的返回值是引用,这个函数调用可以作为左值
test2() = 1000; //test2()返回a,等效 a = 1000
cout << "ref2 :" << ref2 << endl;//1000
cout << "ref2 :" << ref2 << endl;
}
/*2.5引用的本质
本质:引用的本质在C++内部实现是一个指针常量
*/
//发现是引用,转换为 int * const ref = &a;
void funcquote(int &ref) {
ref = 100;//ref是引用,转换为*ref = 100
}
void testfuncquote() {
int a = 10;
//自动转换为 int * const ref = &a; 指针常量是指针指向不可改,也说明为什么引用不可更改 ref存a的地址
int ref = a;
ref = 20; //内部发现ref是引用,自动帮我们转换为 *ref = 20;
cout << "a :" << a << endl;
cout << "ref :" << ref << endl;
funcquote(a);
return ;
}
/*2.5const*/
//常量引用
//const用来修饰形参 , 防止误操作
void _const() {
const int a = 10;
//a = 20; 报错
//int &ref = 10; // 报错非常量引用初始值必须为左值, 没有合法的内存空间
//加入const 就可以了,编译器优化代码,int temp = 10;const int &ref = temp;
const int &ref = 10; //引用必须引一块合法的内存空间!
//ref = 20; 报错 //加入const之后变为只读,不可以修改
}
//打印数据函数 --防止忘记只是用来打印函数的,不修改,加const
void showV(const int& val) {
//val = 1000;
cout << "val :" << val << endl;
}
void test_const() {
_const();
//函数中常利用常量引用防止误操作修改实参
int a = 10;
showV(a);
}
/*3.函数提高
3.1函数默认参数
*1.注意从某个位置有默认值,那么从这个位置往后,从左到右都必须有默认值
*2.如果函数有声明默认函数,函数实现就不能有默认参数
*/
//3.1函数默认参数
int func_han(int a,int b = 20,int c = 30) //默认值
{
return a + b + c;
}
//声明和实现只能有一个有默认参数!, 声明有,实现就不要加参数 , 实现有,声明就不要加参数
// int func_han(int a, int b = 20, int c = 30);//没报错 ,但编译不过-->重复定义
int func_han(int a, int b, int c);
void test_func_han() {
//自己传入数据,可以更改默认值 ,没有就用默认值
//语法 : 返回值类型 函数名 (形参 = 默认值){}
cout << func_han(10,30) << endl;
}
//函数的占位参数
/*
返回值类型 函数名 (数据类型){}
目前阶段的占位参数,我们还用不到,后面的课程会用到
占未参数,还可以有默认参数
int funcz(int a,int = 10) {}
*/
int funcz(int a, int) {
cout << "this is z" << endl;
return 0;
}
void testfuncz() {
funcz(10, 10);//占位参数必须填补
}
/*函数重载 可以让函数名相同,提高复用性
函数的返回值不可以作为函数重载的条件(编译器编译时对相同函数名产生歧义,返回值或函数内容不同函数名相同编译不通过)
*/
void Function_overload() {//函数_重载
cout << "Function_overload()的调用" << endl;
}
void Function_overload(int a) {//函数_重载
cout << "Function_overload(int a)的调用" << endl;
}
void Function_overload(double a) {//函数_重载
cout << "Function_overload(double a)的调用" << endl;
}
void Function_overload(int a,double b) {//函数_重载
cout << "Function_overload(int a,double b)的调用" << endl;
}
void Function_overload(double a,int b) {//函数_重载
cout << "Function_overload(double a,int b)的调用" << endl;
}
void test_Function_overload() {
Function_overload();
Function_overload(10);
Function_overload(3.14);
Function_overload(3.14,10);
Function_overload(10, 3.14);
}
/*函数重载注意事项
* 1.引用作为重载条件
* 2.函数重载碰到函数默认参数
*/
//int 与 const int 属于类型不同
void overload(int &a) {//int &a = 10 不合法 10放在常量区
cout << "overload(int &a)的调用" << endl;
}
void overload(const int &a) {//const int &a = 10 合法,创建一个临时数据指向临时空间
cout << "overload(const int &a)的调用" << endl;
}
void testoverload() {
int a = 10;//a是变量可读可写,会调用可读可写状态的
overload(a);//overload(int &a)的调用
//10放在常量区,int &a语法不通过,const int &a = 10 合法
overload(10);//overload(const int &a)的调用
}
//函数重载碰到默认参数
void __overload(int a, int b = 10) {//函数_重载
cout << "overload(dint a, int b = 10)的调用" << endl;
}
void __overload(int a) {//函数_重载
cout << "overload(double a,int b)的调用" << endl;
}
void test__overload(int a) {
//__overload(10);//出现二义性(歧义) b默认不赋值也可以 ,要尽量避免这种情况出现!
__overload(10,20);//这个就只能是overload(dint a, int b = 10)的调用,且b = 20
}
int main() {
test_Function_overload();
return 0;
}
C++系统学习_01
于 2022-02-22 10:29:52 首次发布