【c++】c++核心编程(1)

本文详细介绍了C++中的内存分区模型,包括代码区、全局区、栈区和堆区,并通过示例代码解释了各区域的作用和管理方式。此外,讨论了引用的概念及其在函数参数传递中的应用,强调了引用的特性。最后,探讨了函数的默认参数、占位参数和重载等提高编程效率的方法,帮助理解函数在C++中的灵活使用。
摘要由CSDN通过智能技术生成

目录

1.1内存分区模型

1.2引用

1.3函数提高


主要针对面向对象编程技巧

面向对象程序设计:以类为基本单位组织编写程序

面向过程程序设计:以函数/过程为基本单位组织编写程序

1.1内存分区模型

内存分为4个区域:

  • 代码区:存放函数体的二进制代码
  • 全局区:存放全局变量和静态变量以及常量
  • 栈区:由编译器自动分配释放
  • 堆区:由程序员自动分配释放,若程序员不释放,则程序结束后由操作系统收回

1.1.1程序运行前

代码区:存放CPU执行的机器指令(二进制代码)

(特点)代码区是共享的,目的是对于频繁被执行的程序,内存中只有一份代码。

              代码区是只读的,目的是防止程序意外被修改了它的指令。

全局区:(特点)该区域的数据在程序运行完后由操作系统释放

#include<iostream>
using namespace std;
//全局变量(g--global)
int g_a = 10;
int g_b = 10;
//const修饰的全局变量
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 << "全局变量a的地址为:" << (int)&g_a << endl;
	cout << "全局变量b的地址为:" << (int)&g_b << endl;
	//静态变量(s--static)
	static int s_a = 10;
	static int s_b = 10;
	cout << "静态变量a的地址为:" << (int)&s_a << endl;
	cout << "静态变量b的地址为:" << (int)&s_b << endl;
	//常量
	//字符串常量
	cout << "字符串常量的地址为:"<< (int)&"hello word" << endl;
	//const修饰的常量
	//const修饰的全局变量(全局常量)
	cout << "全局常量a的地址为:" << (int)&c_g_a << endl;
	cout << "全局常量b的地址为:" << (int)&c_g_b << endl;
	//const修饰的局部变量(局部常量)
	const int c_a = 10;
	const int c_b = 10;
	cout << "局部常量a的地址为:" << (int)&c_a << endl;
	cout << "局部常量b的地址为:" << (int)&c_b << endl;

	system("pause");
	return 0;
}

在一个函数体内就叫局部变量,在一个函数体外就叫全局变量

由上述代码可知:局部常量(const修饰的局部变量)和局部变量不属于全局区;

                             全局变量、静态变量、常量(字符串常量、全局常量)属于全局区。

1.1.2程序运行后

栈区:由编译器自动分配和释放

注意:不要返回局部变量的地址

#include<iostream>
using namespace std;
int * fun()//形参数据也会存放在栈区
{
	int a = 10;
	return &a;
}
int main()
{
	int *p = fun();
	cout << *p<< endl;
	cout << *p << endl;
	system("pause");
	return 0;
}

代码运行如下:

可以发现两个一样的代码,输出的*p的值却不一样,这是为什么?

 栈区的数据在程序执行完后就会自动释放,第一次还会打印正确的是因为编译器做了保留。

堆区:由程序员分配释放,程序结束时由操作系统回收

利用new可以将数据开辟到堆区

#include<iostream>
using namespace std;
int * fun()
{
	//指针的本质还是局部变量,放在栈上,指针保存的数据是放在堆区上的
	int *p= new int(10);//new可以创建堆区数据,返回的是堆区数据的地址
	return p;
}
int main()
{
	int *p = fun();
	cout << *p<< endl;
	cout << *p << endl;
	system("pause");
	return 0;
}

代码运行如下:

 

1.1.3new操作符

new一个数据,则会返回该数据类型的地址,如果想释放堆区的数据,需要利用关键字delete。

如修改如下:

int main()
{
	int *p = fun();
	cout << *p<< endl;
	cout << *p << endl;
	delete p;
	cout << *p << endl;//该数据已被释放,若再访问则会报错。
	system("pause");
	return 0;
}

堆区开辟数组:

释放数组需要加[]

#include<iostream>
using namespace std;
int main()
{
	int *arr = new int[10];
	for (int i = 0; i < 10; i++)
	{
		arr[i] = i + 100;
	}
	for (int i = 0; i < 10; i++)
	{
		cout << arr[i] << endl;
	}
	delete[]arr;
	system("pause");
	return 0;
}

1.2引用

用途:给变量起别名

语法:数据类型 &别名=原名

int main()
{
	int a = 10;
	int &b = a;
	cout << a << "	" << b << endl;
	b = 100;
	cout << a << "	" << b << endl;
	system("pause");
	return 0;
}

代码运行如下:

 

注意:

  • 引用必须要初始化//eg:int &b;---错   引用必须上来就说明是谁的别名
  • 引用初始化后面就不可以改变了//eg:b一开始为a的别名,现在又改为c的别名---错    一旦初始化后就不可以更改了

传参时,可以利用引用让形参修饰实参

#include<iostream>
using namespace std;
void swap(int &a, int &b)
{
	int temp = a;
	a = b;
	b = temp;
}
int main()
{
	int a = 10;
	int b = 20;
	swap(a, b);
	cout << a << "	" << b << endl;
	system("pause");
	return 0;
}

代码运行发现a,b发生了交换,所以引用传递形参改变实参也会发生改变。

注意:

  • 不能返回局部变量的引用//第一次输出正确是因为编译器做了保留,但之后就会输出乱码
  • 如果函数的返回值是引用,则函数调用可以写在等号左边
int& text()
{
	int a = 10;
	return a;
}
int& text1()
{
	static int a = 10;
	return a;
}
int main()
{
	int &n = text();
	cout << n << endl;
	cout << n << endl;
	cout << n << endl;
	int &x = text1();
	cout << x << endl;
	cout << x << endl;
	text1() = 20;
	cout << x << endl;
	cout << x << endl;
	system("pause");
	return 0;
}

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

如下:

常量引用 

作用:主要用来修饰形参,防止误操作(引用修饰后,形参改变了实参就会改变)

eg:int &ref=10;//错    引用需要一个合法的存储空间

const int&ref=10;//加上const之后,编译器将代码修改为int temp=10;int &ref=temp并且ref是不可以修改的

1.3函数提高

1.3.1函数默认参数

语法:返回值类型 函数名(参数=默认值){}

要是我们自己传入参数就用我们自己传入的,要是没有传就用默认的。

注意:1、如果某个位置有默认值,则从这个位置开始往右都要有默认值。

           2、函数的声明和实现只能有一个含默认参数。

#include<iostream>
using namespace std;
int text(int a,int b=10,int c=10)//默认参数
{
	return a + b + c;
}
int main()
{
	cout<<text(10, 20, 30)<<endl;
	system("pause");
	return 0;
}

1.3.2函数占位参数

语法:返回值类型 函数名 (数据类型){}

占位参数必须填补,占位参数中还可以有默认参数

void text(int a,int)//占位参数,目前阶段我们还用不到
{
	cout << "hello word" << endl;
}
int main()
{
	text(10,10);//占位参数必须填补
	system("pause");
	return 0;
}

1.3.3函数重载

就是让函数名相同,提高复用性。

函数重载满足条件:

  • 1.在同一个作用域下
  • 2.函数名相同
  • 3.函数参数类型不同/个数不同/顺序不同(const int a与int a属于类型不同)

注意:函数的返回值不可以做函数重载的条件

eg:一个为void fun(int a,int b)一个为int fun(int a,int b)//错    两个都可以被调用

函数重载的注意事项:

  • 1.引用作为重载的条件
  • 2.函数重载碰到默认参数(会出现二义性,尽量避免)

引用作为重载的条件

void text(int &a)
{
	cout << "hello word" << endl;
}
void text(const int &a)
{
	cout << "hello word!" << endl;

}
int main()
{
	int a = 10;
	text(a);//a是一个变量,是可读可改的而第二个函数是只读的
	text(10);//传入第一个那个函数不合法,而加了const的编译器会做优化

	system("pause");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>