c++入门(20211024版本)

笔者写在前面
毕业了,机械狗太无聊
把以前忘光光的捡起来继续学,从小白开始
慢慢完善c++的笔记。写到哪里是哪里,前后会慢慢补充,格式有点乱,读者勿嗔
至于学到什么深度,最后要做什么暂时不考虑
为了学会而学会?
希望帮助到大家,也希望批评指正,一起进步
20211024

指针
1、引入内存理解
2、指针定义
3、指针大小
4、空指针nullptr
5、野指针
6、const和指针

  1. const修饰指针 —(可以换女朋友(地址)但女朋友名字不可以变(值))
  2. const修饰值(此时就是常量了) —(女朋友的名字可以改)
  3. const即修饰指针,又修饰值(常量)
int a = 10;
int* const p = &a;//修饰a的地址,地址不可换
//const int* p = &a;//修饰a的值,值不可换
cout << p << endl;
cout << *p << endl;

int b=11;
//p = &b;//换b的地址(通过换地址换值)
*p = b;//换b的值
cout << p << endl;
cout << *p << endl;

指针和数组——指针访问数组

double arr[] = { 1,23,4,34,53,5,46,45,64,6,23,423,42 };
double* p =&arr[0];//初始化指向首地址
//以下帮助理解
cout << sizeof(arr) << endl;//104
cout << sizeof(arr[0]) << endl;//8
cout << sizeof(double) << endl;//8
cout << sizeof(double*) << endl;//4,指针的大小取决于编译器的位数,此处是32位编译器,4字节
cout << sizeof(p) << endl;//4
cout << endl;

for (int i = 0; i < 20; i++)
	{
		cout << *p << endl;
		p++;//地址递增相应字节大小(double是8个字节)
	}

指针和函数——值传递和地址传递

结构体:自定义的数据类型
结构体定义:struct 结构体名 { 结构体成员列表 };
其中:结构体成员列表=数据类型1 成员名1;数据类型2 成员名2;
创建结构体变量:(struct可以省略)
1、struct 结构体名 结构体变量名;(不初始化,成员单独初始化)
成员单独初始化:结构体变量名.结构体成员名=初始值;
2、struct 结构体名 结构体变量名={初始值};(初始化)
3、定义结构体时顺便创建结构体变量(少用,看得懂就行)
struct 结构体名 { 结构体成员列表 }结构体变量名;(不初始化)
struct 结构体名 { 结构体成员列表 }结构体变量名={初始值};(初始化)

//结构体定义
struct student
{
	//成员列表
	string name;  //姓名
	int age;      //年龄
}stu3; //结构体变量创建方式3 

int main() {
	//结构体变量创建方式1
	struct student stu1; //struct 关键字可以省略
	stu1.name = "张三";
	stu1.age = 18;
	cout << "姓名:" << stu1.name << " 年龄:" << stu1.age  << endl;
	//结构体变量创建方式2
	struct student stu2 = { "李四",19,60 };
	cout << "姓名:" << stu2.name << " 年龄:" << stu2.age  << endl;
	//结构体变量创建方式3 ,单独初始化结构体
	stu3.name = "王五";
	stu3.age = 18;
	stu3.score = 80;
	cout << "姓名:" << stu3.name << " 年龄:" << stu3.age  << endl;

	system("pause");

	return 0;
}

结构体数组:

struct ss 	{
	string name;
	int age;
};

ss ss_arr[2] = {
	{"her",23},
	{"he",21}
};
for (int i = 0; i < 2; i++)
{
	cout<<"name: " << ss_arr[i].name << "\t"<<"age: " << ss_arr[i].age << endl;
}

结构体指针
理解1:

//定义结构体
struct ss{
	string name;
	int age;
};
//创建结构体变量
ss her = { "her",23};
ss he = { "he", 21 };
//打印结构体变量的内容(成员信息)
cout << he.name<< "\t" << he.age << endl;
cout << her.name << "\t" << her.age << endl;
//通过指针访问
struct ss* p1 = &her;
string *p2 = &her.name;

cout << p1 << endl;
cout << p2 << endl;

理解2:
代码对称,方便理解

struct ss { string name; int age; }s1;//不初始化
s1 = { "s1",  17 };//单独初始化

sturct ss* p = &s1;//struct可以省略
/*ss*/ string* p2 = &s1.name;

嵌套结构体
代码对称,方便理解

//定义学生结构体
struct stduents
{
	string name;
	int age;
};
//定义老师结构体
struct teachers
{
	string name;//字符串变量名,字符串变量名
	int age;//整型类型名,整型变量名
	struct stduents s1;//struct(可以省略) students是结构体类型,s1是结构体变量名(老师的学生s1)
};
//创建学生结构体变量
stduents s1 = { "bill",18 };//students是结构体类型,s1是结构体变量名
//创建老师结构体变量
teachers t1 = { "herry",23,s1 };

cout << t1.name << endl;
cout << t1.age << endl;
cout << t1.s1.name <<" " << t1.s1.age << endl;

多个学生则可以把学生结构体换成结构体数组,如下
试了一下,暂时不会

//定义学生结构体
struct stduents
{
	string name;
	int age;
};
//定义老师结构体
struct teachers
{
	string name;//字符串变量名,字符串变量名
	int age;//整型类型名,整型变量名
	struct stduents ss[];//struct students是结构体类型,ss[2]是结构体变量名(老师的两个学生ss[0]和ss[1])
};
//创建学生结构体变量
stduents ss[2] = { "bill",18,"ada",19};//students是结构体类型,s1是结构体变量名
//创建老师结构体变量
teachers t1 = { "herry",23,ss[2] };

cout << t1.name << endl;
cout << t1.age << endl;
cout << t1.ss[0].name <<" " << t1.ss[0].age << endl;
cout << t1.ss[1].name <<" " << t1.ss[1].age << endl;

补充1:
err:c++中"cout"不明确问题
ans:将using namespace std 删除后重新输入一遍

补充2:
qus:什么是析构函数?
ans:

结构体作为函数参数
值传递

//定义学生结构体
struct stduents
{
	string name;
	int age;
};

void printstudents(struct stduents ss){
	cout << ss.name <<" " << ss.age << endl;
}

int main() {

	//创建学生结构体变量
	struct stduents ss1 = { "bill",18 };//students是结构体类型,ss1是结构体变量名
	
	struct stduents ss2;
	ss2.name = "ada";
	ss2.age = 19;

	printstudents(ss1);
	printstudents(ss2);
	
}

地址传递

//定义学生结构体
struct stduents
{
	string name;
	int age;
};

void printstudents(struct stduents* ss_p){
	cout <<ss_p->name <<" " << ss_p->age << endl;//用->来访问地址中结构体的成员
}

int main() {

	//创建学生结构体变量
	struct stduents ss1 = { "bill",18 };//students是结构体类型,ss1是结构体变量名
	
	struct stduents ss2;
	ss2.name = "ada";
	ss2.age = 19;

	printstudents(&ss1);
	printstudents(&ss2);
	
}

地址传递实参的值会在调用函数内部被拦截修改

//定义学生结构体
struct stduents
{
	string name;
	int age;
};

void printstudents(struct stduents* ss_p){
	ss_p->age = 100;//拦截修改年龄为100
	cout <<ss_p->name <<" " << ss_p->age << endl;//用->来访问地址中结构体的成员
}

int main() {

	//创建学生结构体变量
	struct stduents ss1 = { "bill",18 };//students是结构体类型,ss1是结构体变量名
	
	struct stduents ss2;
	ss2.name = "ada";
	ss2.age = 19;
	//调用函数打印
	printstudents(&ss1);
	printstudents(&ss2);
	
	cout << endl;
	//直接打印
	cout << ss1.name << " " << ss1.age << endl;//年龄变成100
}

c++面向对象编程(oop)
vs设置:
qus1:编辑器
ans:设置方式:工具 – 选项 – 环境 – 字体和颜色 – 字体/大小

程序运行过程中的内存区
代码
全局

乱七八糟的量
基本:

区别,调用函数的参数为实参,定义函数的参数为形参(实参传到形参为函数的入口,调用函数接收返回值为函数的出口)

变量
静态变量

全局变量:函数体外定义。程序的所在部分(甚至其它文件中的代码)都可以使用。
局部变量:函数体内(自定义函数和main函数)。出现在一个作用域内,它们是局限于一个函数的。局部变量默认为auto(自动变量)。

字面常量
const常量(常变量)

关键字
extern
auto自动变量
register寄存器变量,是一种局部变量。
static静态变量,类型引用,静态初始值默认为0
volatile变量
const常量,实例引用

暂存一下,要修改

//全局变量
int g_a = 10;
int g_b = 20;

int main() {
	//局部变量
	int a = 10;
	int b = 10;
	cout << (int)&a << endl;
	cout << (int)&b << endl;
	cout << endl;
	//静态变量	
	static int s_a = 10;
	static int s_b = 10;
	cout << (int)&s_a << endl;
	cout << (int)&s_b << endl;
	cout << endl;
	//面值常量:字符串常量
	cout << (int)&"hello" << endl;
	cout << endl;
	//const常量
	
	//打印全局变量
	cout << (int)&g_a << endl;
	cout << (int)&g_b << endl;
	cout << endl;


全局区
静态变量
字面常量:字符串常量
全局常量
全部变量

栈区:栈区数据由编译器开辟和释放,不要返回栈区数据的地址
局部常量
局部变量
函数参数(形参)

局部变量(栈区)的地址会变动(vs2019中会自动固定,但值不一定固定)

int* func() {
	int num=10;
	return &num;
}

int main() {
	int a = 1;
	int b = 2;
	int *p=func();
	//多次打印
	cout << p << endl;
	cout << *p << endl;
	cout << p << endl;
	cout << *p << endl;
	cout << p << endl;
	cout << *p << endl;
	cout << p << endl;
	cout << *p << endl;

}

堆区
在堆区创建数据:关键字new
释放堆区内存:程序结束;删除堆中数据的地址:delete p;

堆区创建数据

int* func() {
	int* p = new int(10);//堆区整型变量10,地址保存在指针p中
	return p;
}

int main() {
	int *c=func();
	cout << c << endl;//打印地址
	cout << *c << endl;//打印值

}

堆区创建数组

//在堆区创建数组
int* func1() {
	int* p = new int[10];//堆区整型数组变量,有10个变量,(首)地址保存在指针p中
	return p;
}


int main() { 

	int* arr = func1();
	//给数组赋值
	for (int i = 0; i < 10; i++)
	{
		arr[i] =i+10;
	}

	//打印数组
	for (int i = 0; i <10; i++)
	{
		cout << arr[i] << endl;
		cout << &arr[i] << endl;
	}
	//释放数组
	delete[] arr;//[]表示释放数组
}

引用:给变量取别名
语法:int& b = a;
理解:
1、取个别名
2、本质&b=&a
3、b的地址也指向a(不好理解)
4、把a的地址传给b
5、地址一样,物理内存上就是一个

int a = 10;
	cout << a << endl;
	int& b = a;//取个别名,本质&b=&a,即b的地址也指向a,把a的地址传给b,地址一样,物理内存上就是一个块内存。
	b = 20;
	cout << a << endl;
	cout << b << endl;

在这里插入图片描述

//1. 值传递,实参以值传入,在自定义函数中直接换值
void mySwap01(int a, int b) {
	int temp = a;
	a = b;
	b = temp;
}

//2. 地址传递,实参以地址传入,在自定义函数中交换地址
void mySwap02(int* a, int* b) {
	int temp = *a;
	*a = *b;
	*b = temp;
}

//3. 引用传递,实参以值传入,在自定义函数中(以别名作用)本质在交换地址
void mySwap03(int& a, int& b) {
	int temp = a;
	a = b;
	b = temp;
}

int main() {

	int a = 10;
	int b = 20;

	mySwap01(a, b);
	cout << "a:" << a << " b:" << b << endl;

	mySwap02(&a, &b);
	cout << "a:" << a << " b:" << b << endl;

	mySwap03(a, b);
	cout << "a:" << a << " b:" << b << endl;

	system("pause");

	return 0;
}

引用作为函数返回值

int&	test01() {
	int a = 10;//局部变量在栈区
	return a;
}

int& test02() {
	static int a = 10;//静态变量在全局区
	return a;
}

int main() {
	int& ref1 = test01();
	cout << ref1<< endl;//第一次编译器保留
	cout << ref1 << endl;//后续编译器释放就不一定对到了

	int& ref2 = test02();
	cout << ref2 << endl;//10
	cout << ref2 << endl;//10
	cout << ref2 << endl;//10
	cout << ref2 << endl;//10
	cout << ref2 << endl;//10
	cout << ref2 << endl;//10
	cout << ref2 << endl;//10
	cout << ref2 << endl;//10
	cout << ref2 << endl;//10
	cout << endl;

	test02() = 1000;//函数的返回值是调用可以作为左值
	cout << ref2<< endl;//1000

}

引用的本质:引用的本质在c++内部实现是一个指针常量

void func(int& ref){//发现ref是引用,转换为 int* const ref = &a;
	ref = 100; // 发现ref是引用,自动转换:*ref = 100
}

int main(){
	int a = 10;       
	int& ref = a; //发现ref是引用,自动转换:int* const ref = &a; 指针常量是指针指向不可改,也说明为什么引用不可更改 
	ref = 20; //发现ref是引用,自动转换为:*ref = 20;
    cout << "a:" << a << endl;
    cout << "ref:" << ref << endl;
    
	func(a);
	return 0;
}

常量引用:常量引用主要用来修饰形参,防止误操作
双const

函数高级
函数定义:

参数列表默认值
1、如果某个位置参数有默认值,那么从这个位置往后,从左向右,必须都要有默认值
2、调用时,有实参用实参,无实参用默认值
3、声明有默认参数,函数的实现就不能有默认参数

占位参数

函数重载
同一个作用域下,函数名称相同
编译器靠函数的参数(函数的入口)确定调用的函数,调用同名的哪一个函数取决于参数对应原则

函数参数类型不同 或者 个数不同 或者 顺序不同
函数的返回值不可以作为函数重载的条件

类型不同,const int 和int就是不同,可以发生函数重载

坑1:
引用作为函数重载的条件

坑2:
默认参数

oop

eg1:

const double PI = 3.14;

class circle
{
public:
	int r;
	double s() {
		double s = PI * r * r;
		return s;
	}
	double c() {
		double c = 2 * PI * r;
		return c;
	}
};

int main() {
	circle c1;
	cin>>	 c1.r ;
	double s = c1.s();
	double c = c1.c();
	cout << s << endl;
	cout << c << endl;

	system("pause");
	return 0;
}

eg2:

class student
{
public:
	//属性
	string t_name;
	int t_age;
	//行为
	//打印学生信息
	void printstudents() {
		cout << t_name <<" " << t_age << endl;
	}
	//创建成员方法设置名字
		void get_name(string name) {
		t_name = name;
	}
	//创建成员方法设置年龄
	void get_age(int age) {
		t_age = age;
	}
	
};

int main() {
	student s1;
	//s1.t_name = "herry2";
	//s1.t_age = 18;
	s1.get_name ( "herry");
	s1.get_age ( 18);
	s1.printstudents();

}

三种权限
public:成员在类内可以访问,在类外可以访问
protected:成员在类内可以访问,在类外不能访问。子可以访问父保护权限
private:成员在类内可以访问,在类外不能访问。子不可以访问父保护权限

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值