02-c++核心编程

1.c++内存分区

代码:函数体
全局:全局,静态,全局常量,字符串常量
栈:编译器自动分配释放,存放参数值和局部变量
堆:程序员分配和释放,结束时操作系统回收

分区意义,不同区域,生命周期不同

1.1 程序执行前

编译后exe

两个区域

1.1.1 代码区:

cpu执行机器指令
共享:多执行,一份码
只读

1.1.2全局区

全局、静态、字符串
==程序结束==,==操作系统==释放
非全局区:除==静态和字符串==外的所有==局部量==
#include<iostream>
using namespace std;

int g_a = 10;
int g_b = 10;

const int c_g_a = 10;
const int c_g_b = 10;

int main() {
	//局部变量
	int a = 10;
	int b = 10;

	//打印地址
	cout << "局部变量a地址为: " << (int)&a << endl;
	cout << "局部变量b地址为: " << (int)&b << endl;

	cout << "全局变量g_a地址为: " << (int)&g_a << endl;
	cout << "全局变量g_b地址为: " << (int)&g_b << endl;

	//静态变量
	static int s_a = 10;
	static int s_b = 10;

	cout << "静态变量s_a地址为: " << (int)&s_a << endl;
	cout << "静态变量s_b地址为: " << (int)&s_b << endl;

	cout << "字符串常量地址为: " << (int)&"hello world" << endl;
	cout << "字符串常量地址为: " << (int)&"hello world1" << endl;

	cout << "全局常量c_g_a地址为: " << (int)&c_g_a << endl;
	cout << "全局常量c_g_b地址为: " << (int)&c_g_b << endl;

	const int c_l_a = 10;
	const int c_l_b = 10;
	cout << "局部常量c_l_a地址为: " << (int)&c_l_a << endl;
	cout << "局部常量c_l_b地址为: " << (int)&c_l_b << endl;

	system("pause");

	return 0;

}

在这里插入图片描述

1.2 程序运行

1.2.1 栈区

存储参数值和局部变量
编译器函数执行完自动分配释放
不要在方法体里返回局部变量地址

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

int main() {

	int *p = func();

	cout << *p << endl;//第一次会正确输出,因为编译器会作保留
	cout << *p << endl;//d第二次就会有问题
	system("pause");

	return 0;
	}

在这里插入图片描述

1.2.2 堆区

由程序员管理开辟和释放
不释放,程序结束时由操作系统回收
利用new关键字进行开辟内存(返回的是地址编号)

指针是局部变量,在栈上。
指针指向的地址在堆区(数据在堆区)

#include<iostream>
using namespace std;

int* func()
{
	int* a = new int(10);
	return a;
}

int main() {

	int* p = func();

	cout << *p << endl;
	cout << *p << endl;
	cout << *p << endl;
	system("pause");

	return 0;
}

在这里插入图片描述

1.2.3 new操作符

语法: int* a = new 数据类型 (值)
创建数组:int* a = new int[10];
释放单个: delete 指针 delete a
释放数组:delete[] arr;

int* func()
{
	int* a = new int(10);
	return a;
}

int main() {

	int* p = func();

	cout << *p << endl;
	cout << *p << endl;
	cout << *p << endl;
	system("pause");
	delete p;
	cout << *p << endl;

	return 0;
}

在这里插入图片描述

int* arr = new int[10];
delete[] b;

2.引用

给变量起别名
语法: 数据类型 &别名 = 原名

int a = 10;
int &b = a;

在这里插入图片描述

2.1 注意事项

1.不能光声明不初始化,一声明就必须初始化
2.引用在初始化后,不可以改变(它永远代表它初始化的那块内存,给引用赋值就是给那块内存赋值,而不是让引用指向新变量)

int a = 10;
int b = 20;
//int &c; //错误,引用必须初始化

int &c = a; //一旦初始化后,就不可以更改
c = b; //这是赋值操作,不是更改引用 不是c变成了b的引用,而是a的值变成了b的值

在这里插入图片描述

2.2 引用作形参

指针作参数:传地址
引用作形参:传自身

//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;
}
	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;

在这里插入图片描述

2.3 引用作返回值

引用是可以作为函数的返回值
如果函数做左值(被赋值对象),那么必须返回引用
注意:不要返回局部变量引用
局部变量地址在栈区,被释放了

int& test01() {
	int a = 10; //局部变量
	return a;
}
int& test02() {
	static int a = 20;
	return a;
}

//不能返回局部变量的引用
int& ref = test01();
int& ref2 = test02();
test02() = 1000;
cout << "ref2 = " << ref2 << endl;
cout << "ref2 = " << ref2 << endl;

在这里插入图片描述

2.4 引用的本质

本质:引用的本质在c++内部实现是一个指针常量.(保存地址)
初始化:int& ref = a; 相当于int* const ref = &a;
赋值:ref = 20;相当于*ref = 20;
使用的时候只要想操控它就是操控它初始化的那块内存值
上诉转化编译期会自动完成

2.5 常量引用

1.普通引用初始化必须引用合法内存空间,而不能是常量池中的值

//int& ref = 10;  引用本身需要一个合法的内存空间,因此这行错误
int& c = a; //一旦初始化后,就不可以更改
c = 30;

2.常量引用可以直接初始化为常量值

const int& ref =10;
ref = b;//不允许再通过引用赋值了。

编译期会自动优化为 int temp = 10; const int& ref = temp;

3.作用场景
做形参,防止被函数改值

问题:这么做比直接值传递有什么优势
操作时实际上就是操作原对象本身, 这样的传引用可以避免对象传递时产生临时对象. 减少很多不必要的时间和空间的开销

//引用使用的场景,通常用来修饰形参
void showValue(const int& v) {
	//v += 10;
	cout << v << endl;
}

//函数中利用常量引用防止误操作修改实参
	int a = 10;
	showValue(a);

3.函数

1.可有默认参数
一个有默认值,则从它往后的每一个参数都需要有

int func(int a, int b = 10, int c = 10) {
	return a + b + c;
}

2.可有占位参数,必须填补

void func(int a, int) {
	cout << "this is func" << endl;
}
func(10,10); //占位参数必须填补

3.3函数重载

3.3.1 重载条件

  • 同一个作用域下
  • 函数名称相同
  • 函数参数类型不同 或者 个数不同 或者 顺序不同
    注意: 函数的返回值类型不同不可以作为函数重载的条件
#include<iostream>
using namespace std;
void func(double a, int b)
{
	cout << "func (double a ,int b)的调用!" << endl;
}
void func(double a, int b)
{
	cout << "func (double a ,int b)的调用!" << endl;
}

int main() {
	func(3.14, 10);
	system("pause");

	return 0;

}

在这里插入图片描述

3.3.2 注意事项

1.引用作为参数类型
常量引用直接传值,非常量引用传参数名

void func(int &a)
{
	cout << "func (int &a) 调用 " << endl;
}

void func(const int &a)
{
	cout << "func (const int &a) 调用 " << endl;
}

	int a = 10;
	func(a); //调用无const
	func(10);//调用有const

2.默认参数导致歧义问题

void func2(int a, int b = 10)
{
	cout << "func2(int a, int b = 10) 调用" << endl;
}

void func2(int a)
{
	cout << "func2(int a) 调用" << endl;
}
func2(10);

在这里插入图片描述

4.类

三大特性:封装,继承。多态
C++认为万事万物都皆为对象,对象上有其属性和行为

4.1 封装 encapsulation

1.意义:把属性和行为作为一个整体

const double PI = 3.14;
class Circle {
public:
	int m_r;

	double getZC() {
		return 2 * PI * m_r;
	}
};
int main() {
	Circle c1;
	c1.m_r = 2;
	cout << c1.getZC() << endl;
	system("pause");

	return 0;
}

2. 访问控制:

  1. public 公共权限 类内可以访问 类外可以访问
  2. protected 保护权限 类内可以访问 类外不可以访问 儿子可访问
  3. private 私有权限 儿子不能访问
class Circle {
public:
	int m_r;

	double getZC() {
		return 2 * PI * m_r;
	}

	void func() {
		m_type = "circle";
		password = 123;
	}
protected:
	string m_type;
private:
	int password;
};
int main() {
	Circle c1 ;

	cout << c1.getZC() << endl;
	system("pause");

	return 0;
}

在这里插入图片描述

3.和struct区别

在C++中 struct和class唯一的区别就在于 默认的访问权限不同

class C1 {
	int m_1;
};

struct C2 {
	int m_2;

};
C1 c1;
c1.m_1 = 1;//会报错
C2 c2 ;
c2.m_2 = 1;

在这里插入图片描述

4.成员属性私有化

原因:
1.可以自己控制读写权限
2.可以检测写操作有效性

class Person {
public:

	//姓名设置可读可写
	void setName(string name) {
		m_Name = name;
	}
	string getName()
	{
		return m_Name;
	}


	//获取年龄 
	int getAge() {
		return m_Age;
	}
	//设置年龄
	void setAge(int age) {
		if (age < 0 || age > 150) {
			cout << "你个老妖精!" << endl;
			return;
		}
		m_Age = age;
	}

	//情人设置为只写
	void setLover(string lover) {
		m_Lover = lover;
	}

private:
	string m_Name; //可读可写  姓名
	
	int m_Age; //只读  年龄

	string m_Lover; //只写  情人
};


int main() {

	Person p;
	//姓名设置
	p.setName("张三");
	cout << "姓名: " << p.getName() << endl;

	//年龄设置
	p.setAge(50);
	cout << "年龄: " << p.getAge() << endl;

	//情人设置
	p.setLover("苍井");
	//cout << "情人: " << p.m_Lover << endl;  //只写属性,不可以读取

	system("pause");

	return 0;
}

3.形参尽量传引用,取值尽量用方法

class Cube {
private:
	double a;
public:
	double getA() {
		return a;
	}
	void setA(double x) {
		a = x;
	}
	bool myEquals(Cube &x1) {
		return x1.getA() == a;
	}
	double getArea() {
		return a * a;
	}
	double getVolume() {
		return a * a * a;
	}

};
bool myEqual1(Cube& x1, Cube& x2) {
	return x1.getA() == x2.getA();
}

4.2 对象初始化与清理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值