打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
C++入门到理解阶段二核心篇(1)——c++面向对象概述、内存分析、引用

1.c++内存分区模型

c++程序在运行的过程中,内存会被划分为以下四个分区

代码区:程序的所有程序的二进制代码,包括注释会被放到此区

全局区:存放静态变量、全局变量、常量(字符串常量和const修饰的常量),此区的数据将在程序结束后由操作系统释放

using namespace std;//不在任何函数内的变量是全局变量int a = 10;int b = 23;int main() {	//在某个函数内的变量	int c = 12;	cout << (int)&a << endl;	cout << (int)&b << endl;	cout << (int)&c << endl;}

栈区:用于存放局部变量、函数参数等,是由编译器自动释放和分配,所以不能让栈区返回一个地址,

#include <iostream>#include <string>using namespace std;int* f() {	int a = 10;	return &a;//栈区不要返回地址。局部变量是由编译器自动释放和分配}int main() {		int* p = f();	cout << *p;//10 第一次编译器会做保留	cout << *p;//不会打印10}

堆区:存储对象(使用new操作符,后面会介绍)由程序员分配释放,若我们不释放,程序结束由操作系统释放

c++中通过new关键字将数据开辟到堆区

#include <iostream>using namespace std;int* f() {	/*	*1.指针本身也是局部变量,存放在栈长中,但是保存的数据在堆中	2.new关键字开辟一块堆区,返回的是该数据类型的指针	*/	int *a = new int(10);	return a;}int main() {	int* p = f();	cout << *p;//10	cout << *p;//10	//3.堆区的数据程,序员可以通过该delete释放	delete p;	//cout << *p;异常}

 如果是new一个数组

//new一个数组int* arr = new int[10];//释放一个数组delete[] arr;

注意

代码区和全局区是程序编译成exe可执行文件的时候就已经有了,但是栈区和堆区是程序exe文件执行后产生的

2.为什么划分内存(内存划分意义)

将不同的数据放在不同的区域,赋予不同的生命周期,提高编程灵活程度

3.引用

使用引用给一个变量起别名

#include <iostream>using namespace std;int main() {		int a = 10;	/*1.定义引用的格式  数据类型 &别名=原名	*2.引用必需要初始化	*3.引用初始化后,不可更改	*/	int& b = a;	cout << b;//10}

前面文章中的地址传递会修改实参,值传递不会修改实参,引用作为函数参数会修改实参,简化使用指针修改实参的复杂过程

#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;//20	cout << b;//10}

 局部变量不能作为函数的返回值返回

#include <iostream>using namespace std;int& f() {	int a = 10;//栈区中的局部变量在函数执行完后释放	return a;}int main() {		int &a = f();	cout << a;//10 编译器保留	cout << a;//不在是10}

如果是局部静态变量,可以返回

#include <iostream>using namespace std;int& f() {	static int a = 10;//栈区中的局部变量在函数执行完后释放	return a;}int main() {		int &a = f();	cout << a;//10	cout << a;//10}
#include <iostream>using namespace std;int& f() {	static int a = 10;//栈区中的局部变量在函数执行完后释放	return a;}int main() {		int &a = f();	cout << a;//10	cout << a;//10	f() = 100;//如果函数的返回是一个引用,可以作为左值	cout << a;//100	cout << a;//100}

引用本质是指针常量

int main() {		int a = 1;	//内部发现是引用,自动转成指针常量 int * const b=&a;	int& b = a;	b = 2;//内部发现是引用,自动转成*b=20;	cout << a;//2	cout << b;//2}

 常量引用

#include <iostream>using namespace std;//使用const修改函数形参,防止误操作void f(const int& a) {	//a = 100;不允许修改}int main() {		int& b = 1;//引用本身需要一个合法内存空间,所以这行代码有误	int a = 10;	f(a);}

4.函数相关

前面c++基础系列有关函数知识有所描述,这里补充一些函数高级知识

1.c++中函数可以有默认值

#include <iostream>using namespace std;//1.c++中函数可以有默认值,并且某个位置有了默认值,那么从这个位置开始左到右都的有默认值int f(int a, int b = 10,int c=20) {	return a + b + c;}int main() {		int a = 10;	//2.如果函数有默认值,当我们传值使用传递的值,不传值使用默认的	cout<<f(a);//40	cout << f(a, 20);//50}//3.声明和实现只能有一个有默认参数int f1(int a, int b = 10);int f1(int a, int b) {	return a + b;}

2.c++函数中可以有占位参数用来占位,调用函数必需填补该位置

#include <iostream>using namespace std;//1.只写一个数据类型就是占位void f(int a,int) {	cout << "test";}//2.占位参数可以有默认值void f1(int a, int=10) {	cout << "test";}int main() {		int a = 10;	f(a, 10);//占位参必须填补}

3.函数重载

定义:同一个作用域下,两个函数参数类型不同或者参数顺序不同或者个数不同。此时这两个函数名字可以相同。提高复用性

#include <iostream>using namespace std;void f(int a,int b) {	cout << "test";}void f(int a) {	cout << "test";}int main() {		int a = 10;	f(a, 10);}

注意:函数返回值不能作为函数重载的条件

4.引用也可作为函数重载条件

#include <iostream>using namespace std;void f(int &a) {//int &a=10;不合法	cout << "test";}void f(const int &a) {//const int &a=10;合法	cout << "test111";}int main() {		int a = 10;	f(a);//test	f(10);//test111}

5.函数重载遇到默认参数需要注意

void f(int a,int b=10) {//int &a=10;不合法	cout << "test";}void f(int a) {//const int &a=10;合法	cout << "test111";}int main() {		int a = 10;	f(a);//报错,出现二义性}

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
【C 】函数讲解
C++ 变量作用域
【博文连载】C++中的“命名空间”
两个数较大值如何求取
C++对C语言的非面向对象特性扩充(3)
C++ 学习笔记1 - 日志 - 邱泳天 - 血与荣誉SNS平台 - Powered by ...
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服