C++内存管理

C++ 内存管理

构建几个类和结构体:

class UpperClass
{
public:
	int a;
	int b;
	int c;
};

struct UpperStruct
{
public:
	int a;
	int b;
	int c;
};

class DownClass
{
public:
	int d;
	int e;
	int f;
};

class DownStruct
{
public:
	int d;
	int e;
	int f;
};

class DownTClass:public DownClass
{
public:
	int g;
	int h;
	int i;
};

测试几个类的大小和地址:

void Test01()
{
    UpperClass upperClass1;
    UpperStruct upperStruct1;

    upperClass1.a = 100;
    upperStruct1.a = 200;

    cout << "up1地址:" << (int)&upperClass1 << ";up1大小" << sizeof(upperClass1) << endl;
    cout << "up1-a地址:" << (int)&upperClass1.a << ";up1-a大小" << sizeof(upperClass1.a) << endl;
    cout << "up1-b地址:" << (int)&upperClass1.b << ";up1-b大小" << sizeof(upperClass1.b) << endl;
    cout << "us1地址:" << (int)&upperStruct1 << ";us1大小" << sizeof(upperStruct1) << endl;
    cout << "us1-a地址:" << (int)&upperStruct1.a << ";us1-a大小" << sizeof(upperStruct1.a) << endl;
    cout << "us1-b地址:" << (int)&upperStruct1.b << ";us1-b大小" << sizeof(upperStruct1.b)<<endl;

    cout << "**********************************************************************" << endl;
    UpperClass* upperClass2= new UpperClass();
    UpperStruct* upperStruct2= new UpperStruct();

    upperClass2->a = 100;
    upperStruct2->a = 200;
    
    cout << "up2地址:" << (int)upperClass2 << ";up2大小" << sizeof(*upperClass2) << endl;
    cout << "up2-a地址:" << (int)&upperClass2->a << ";up2-a大小" << sizeof(upperClass2->a) << endl;
    cout << "up2-b地址:" << (int)&upperClass2->b << ";up2-b大小" << sizeof(upperClass2->b) << endl;
    cout << "us2地址:" << (int)upperStruct2 << ";us2大小" << sizeof(*upperStruct2) << endl;
    cout << "us2-a地址:" << (int)&upperStruct2->a << ";us2-a大小" << sizeof(upperStruct2->a) << endl;
    cout << "us2-b地址:" << (int)&upperStruct2->b << ";us2-b大小" << sizeof(upperStruct2->b) << endl;
}

得到的结果:

up1地址:-1949304304;up1大小12
up1-a地址:-1949304304;up1-a大小4
up1-b地址:-1949304300;up1-b大小4
us1地址:-1949304288;us1大小12
us1-a地址:-1949304288;us1-a大小4
us1-b地址:-1949304284;us1-b大小4
**********************************************************************
up2地址:1855195248;up2大小12
up2-a地址:1855195248;up2-a大小4
up2-b地址:1855195252;up2-b大小4
us2地址:1855196048;us2大小12
us2-a地址:1855196048;us2-a大小4
us2-b地址:1855196052;us2-b大小4

结论:
通过new关键字定义的对象,存储位置都在堆区,不通过new关键字定义的对象,生成位置都在栈区;
通过new关键字定义的所有对象的成员都生成在堆区
类的地址为类的第一个对象所在的地址

假设:
类的地址,通过字节大小可以判断类的其他成员的地址,进而获取类中所有的对象

查看引用发生的变化

改造UpperClass 加入类对象作为成员:

class UpperClass
{
public:
	int a;
	DownClass b;
	int c;
};

struct UpperStruct
{
public:
	int a;
	DownClass b;
	int c;
};

运行test01得到的结果:

void Test01()
{
    UpperClass upperClass1;
    UpperStruct upperStruct1;

    upperClass1.a = 100;
    upperStruct1.a = 200;
    DownClass dc1{1,1,1};
    upperClass1.b = dc1;
    upperStruct1.b = dc1;

    cout << "up1地址:" << (int)&upperClass1 << ";up1大小" << sizeof(upperClass1) << endl;
    cout << "dc1地址:" << (int)&dc1 << ";dc1大小" << sizeof(dc1) << endl;
    cout << "up1-a地址:" << (int)&upperClass1.a << ";up1-a大小" << sizeof(upperClass1.a) << endl;
    cout << "up1-b地址:" << (int)&upperClass1.b << ";up1-b大小" << sizeof(upperClass1.b) << endl;
    cout << "us1地址:" << (int)&upperStruct1 << ";us1大小" << sizeof(upperStruct1) << endl;
    cout << "us1-a地址:" << (int)&upperStruct1.a << ";us1-a大小" << sizeof(upperStruct1.a) << endl;
    cout << "us1-b地址:" << (int)&upperStruct1.b << ";us1-b大小" << sizeof(upperStruct1.b)<<endl;

    cout << "**********************************************************************" << endl;
    UpperClass* upperClass2= new UpperClass();
    UpperStruct* upperStruct2= new UpperStruct();

    upperClass2->a = 100;
    upperStruct2->a = 200;
    DownClass* dc2 = new DownClass();
    upperClass2->b = *dc2;
    upperStruct2->b = *dc2;
    
    cout << "up2地址:" << (int)upperClass2 << ";up2大小" << sizeof(*upperClass2) << endl;
    cout << "dc2地址:" << (int)dc2 << ";dc大小" << sizeof(*dc2) << endl;
    cout << "up2-a地址:" << (int)&upperClass2->a << ";up2-a大小" << sizeof(upperClass2->a) << endl;
    cout << "up2-b地址:" << (int)&upperClass2->b << ";up2-b大小" << sizeof(upperClass2->b) << endl;
    cout << "us2地址:" << (int)upperStruct2 << ";us2大小" << sizeof(*upperStruct2) << endl;
    cout << "us2-a地址:" << (int)&upperStruct2->a << ";us2-a大小" << sizeof(upperStruct2->a) << endl;
    cout << "us2-b地址:" << (int)&upperStruct2->b << ";us2-b大小" << sizeof(upperStruct2->b) << endl;
}
up1地址:1970666848;up1大小20
dc1地址:1970666832;dc1大小12
up1-a地址:1970666848;up1-a大小4
up1-b地址:1970666852;up1-b大小12
us1地址:1970666872;us1大小20
us1-a地址:1970666872;us1-a大小4
us1-b地址:1970666876;us1-b大小12
**********************************************************************
up2地址:-1795421584;up2大小20
dc2地址:-1795422000;dc大小12
up2-a地址:-1795421584;up2-a大小4
up2-b地址:-1795421580;up2-b大小12
us2地址:-1795420592;us2大小20
us2-a地址:-1795420592;us2-a大小4
us2-b地址:-1795420588;us2-b大小12

结论:class和struct在内存中的大小包含其中成员类的大小,类的成员对象通过赋值操作后将外部定义的对象拷贝到类的地址内

查看堆和栈之间的数据交互

运行Test02,通过栈堆调用

void Test02()
{
    UpperClass upperClass1;
    UpperStruct upperStruct1;

    upperClass1.a = 100;
    upperStruct1.a = 200;

    DownClass* dc1 = new DownClass();

    upperClass1.b = *dc1;
    upperStruct1.b = *dc1;

    cout << "up1地址:" << (int)&upperClass1 << ";up1大小" << sizeof(upperClass1) << endl;
    cout << "dc1地址:" << (int)dc1 << ";dc1大小" << sizeof(*dc1) << endl;
    cout << "up1-a地址:" << (int)&upperClass1.a << ";up1-a大小" << sizeof(upperClass1.a) << endl;
    cout << "up1-b地址:" << (int)&upperClass1.b << ";up1-b大小" << sizeof(upperClass1.b) << endl;
    cout << "us1地址:" << (int)&upperStruct1 << ";us1大小" << sizeof(upperStruct1) << endl;
    cout << "us1-a地址:" << (int)&upperStruct1.a << ";us1-a大小" << sizeof(upperStruct1.a) << endl;
    cout << "us1-b地址:" << (int)&upperStruct1.b << ";us1-b大小" << sizeof(upperStruct1.b) << endl;

    cout << "**********************************************************************" << endl;
    UpperClass* upperClass2 = new UpperClass();
    UpperStruct* upperStruct2 = new UpperStruct();

    upperClass2->a = 100;
    upperStruct2->a = 200;

    DownClass dc2;

    cout << "up2地址:" << (int)upperClass2 << ";up2大小" << sizeof(*upperClass2) << endl;
    cout << "dc2地址:" << (int)&dc2 << ";dc大小" << sizeof(dc2) << endl;
    cout << "up2-a地址:" << (int)&upperClass2->a << ";up2-a大小" << sizeof(upperClass2->a) << endl;
    cout << "up2-b地址:" << (int)&upperClass2->b << ";up2-b大小" << sizeof(upperClass2->b) << endl;
    cout << "us2地址:" << (int)upperStruct2 << ";us2大小" << sizeof(*upperStruct2) << endl;
    cout << "us2-a地址:" << (int)&upperStruct2->a << ";us2-a大小" << sizeof(upperStruct2->a) << endl;
    cout << "us2-b地址:" << (int)&upperStruct2->b << ";us2-b大小" << sizeof(upperStruct2->b) << endl;
}

运行结果:

up1地址:-737085216;up1大小20
dc1地址:213126032;dc1大小12
up1-a地址:-737085216;up1-a大小4
up1-b地址:-737085212;up1-b大小12
us1地址:-737085192;us1大小20
us1-a地址:-737085192;us1-a大小4
us1-b地址:-737085188;us1-b大小12
**********************************************************************
up2地址:213125904;up2大小20
dc2地址:-737085168;dc大小12
up2-a地址:213125904;up2-a大小4
up2-b地址:213125908;up2-b大小12
us2地址:213125936;us2大小20
us2-a地址:213125936;us2-a大小4
us2-b地址:213125940;us2-b大小12

可以发现,dc1通过new创建,存在于堆区。up1及us1均在栈区,通过赋值操作,将存在于堆区的dc1拷贝到栈区;

dc2在栈区创建,up2及us2均在堆区,通过复制操作,将存在于栈区的dc2拷贝到堆区的类对象内。

##父类与子类的交互

如Test03()

void Test03()
{
    UpperClass upperClass1;
    UpperStruct upperStruct1;

    upperClass1.a = 100;
    upperStruct1.a = 200;

    DownClass* dc1 = new DownTClass();
    DownTClass* dc3 = new DownTClass();

    upperClass1.b = *dc3;
    upperStruct1.b =*dc3;

    cout << "up1地址:" << (int)&upperClass1 << ";up1大小" << sizeof(upperClass1) << endl;
    cout << "dc1地址:" << (int)dc1 << ";dc1大小" << sizeof(*dc1) << endl;
    cout << "dc3地址:" << (int)dc3 << ";dc3大小" << sizeof(*dc3) << endl;
    cout << "up1-a地址:" << (int)&upperClass1.a << ";up1-a大小" << sizeof(upperClass1.a) << endl;
    cout << "up1-b地址:" << (int)&upperClass1.b << ";up1-b大小" << sizeof(upperClass1.b) << endl;
    cout << "us1地址:" << (int)&upperStruct1 << ";us1大小" << sizeof(upperStruct1) << endl;
    cout << "us1-a地址:" << (int)&upperStruct1.a << ";us1-a大小" << sizeof(upperStruct1.a) << endl;
    cout << "us1-b地址:" << (int)&upperStruct1.b << ";us1-b大小" << sizeof(upperStruct1.b) << endl;

    cout << "**********************************************************************" << endl;
    UpperClass* upperClass2 = new UpperClass();
    UpperStruct* upperStruct2 = new UpperStruct();

    upperClass2->a = 100;
    upperStruct2->a = 200;

    DownClass dc2{1,1,1};
    upperClass2->b = dc2;
    upperStruct2->b = dc2;

    cout << "up2地址:" << (int)upperClass2 << ";up2大小" << sizeof(*upperClass2) << endl;
    cout << "dc2地址:" << (int)&dc2 << ";dc大小" << sizeof(dc2) << endl;
    cout << "up2-a地址:" << (int)&upperClass2->a << ";up2-a大小" << sizeof(upperClass2->a) << endl;
    cout << "up2-b地址:" << (int)&upperClass2->b << ";up2-b大小" << sizeof(upperClass2->b) << endl;
    cout << "us2地址:" << (int)upperStruct2 << ";us2大小" << sizeof(*upperStruct2) << endl;
    cout << "us2-a地址:" << (int)&upperStruct2->a << ";us2-a大小" << sizeof(upperStruct2->a) << endl;
    cout << "us2-b地址:" << (int)&upperStruct2->b << ";us2-b大小" << sizeof(upperStruct2->b) << endl;
}

程序运行结果:

void Test03()
{
    UpperClass upperClass1;
    UpperStruct upperStruct1;

    upperClass1.a = 100;
    upperStruct1.a = 200;

    DownClass* dc1 = new DownTClass();
    DownTClass* dc3 = new DownTClass();

    upperClass1.b = *dc3;
    upperStruct1.b =*dc3;

    cout << "up1地址:" << (int)&upperClass1 << ";up1大小" << sizeof(upperClass1) << endl;
    cout << "dc1地址:" << (int)dc1 << ";dc1大小" << sizeof(*dc1) << endl;
    cout << "dc3地址:" << (int)dc3 << ";dc3大小" << sizeof(*dc3) << endl;
    cout << "up1-a地址:" << (int)&upperClass1.a << ";up1-a大小" << sizeof(upperClass1.a) << endl;
    cout << "up1-b地址:" << (int)&upperClass1.b << ";up1-b大小" << sizeof(upperClass1.b) << endl;
    cout << "us1地址:" << (int)&upperStruct1 << ";us1大小" << sizeof(upperStruct1) << endl;
    cout << "us1-a地址:" << (int)&upperStruct1.a << ";us1-a大小" << sizeof(upperStruct1.a) << endl;
    cout << "us1-b地址:" << (int)&upperStruct1.b << ";us1-b大小" << sizeof(upperStruct1.b) << endl;

    cout << "**********************************************************************" << endl;
    UpperClass* upperClass2 = new UpperClass();
    UpperStruct* upperStruct2 = new UpperStruct();

    upperClass2->a = 100;
    upperStruct2->a = 200;

    DownClass dc2{1,1,1};
    upperClass2->b = dc2;
    upperStruct2->b = dc2;

    cout << "up2地址:" << (int)upperClass2 << ";up2大小" << sizeof(*upperClass2) << endl;
    cout << "dc2地址:" << (int)&dc2 << ";dc大小" << sizeof(dc2) << endl;
    cout << "up2-a地址:" << (int)&upperClass2->a << ";up2-a大小" << sizeof(upperClass2->a) << endl;
    cout << "up2-b地址:" << (int)&upperClass2->b << ";up2-b大小" << sizeof(upperClass2->b) << endl;
    cout << "us2地址:" << (int)upperStruct2 << ";us2大小" << sizeof(*upperStruct2) << endl;
    cout << "us2-a地址:" << (int)&upperStruct2->a << ";us2-a大小" << sizeof(upperStruct2->a) << endl;
    cout << "us2-b地址:" << (int)&upperStruct2->b << ";us2-b大小" << sizeof(upperStruct2->b) << endl;
}

运行结果

up1地址:-1854210944;up1大小20
dc1地址:1278937264;dc1大小12
dc3地址:1278938800;dc3大小24
up1-a地址:-1854210944;up1-a大小4
up1-b地址:-1854210940;up1-b大小12
us1地址:-1854210920;us1大小20
us1-a地址:-1854210920;us1-a大小4
us1-b地址:-1854210916;us1-b大小12
**********************************************************************
up2地址:1278937296;up2大小20
dc2地址:-1854210960;dc大小12
up2-a地址:1278937296;up2-a大小4
up2-b地址:1278937300;up2-b大小12
us2地址:1278937008;us2大小20
us2-a地址:1278937008;us2-a大小4
us2-b地址:1278937012;us2-b大小12

结论:
当用父类声明,用子类新建实例时,子类中的对象成员会消失。
因此在class中声明有继承关系的成员对象时,需要用到指针。
将对象单独声明出来,进行统一管理。

有个奇怪的问题:

在虚拟机上sizeof一个类永远都是8个字节,但是在本地运行是真实大小。

传递参数时,通过const MyParentClass& 来引用对象可以保证子类数据的完整性

通过智能指针管理内存

shared_ptr

unique_ptr

数据之间的传递

接下来构造以下类

#pragma once
#include <iostream>
#include <string>
#include <vector>
using namespace std;

enum PersonType
{
	per,
	tea,
};
class Person
{
public:
	Person();
	Person(const Person& src);
	~Person();
	Person& Clone(const Person& oriPer);
	int name;
	int age;
	PersonType type;
};

class Teacher:public Person
{
public:
	Teacher();
	Teacher(const Teacher& teacher);
	~Teacher();
	int school;
};

class School
{
public:
	School();
	vector<Teacher>* teacherList;
};

#include "CloneTest.h"

Person::Person()
{
	this->type = PersonType::per;
}
Person::Person(const Person& src):type(src.type),
name(src.name),
age(src.age)
{
}
Person::~Person()
{
}
Person& Person::Clone(const Person& oriPer)
{
	if (oriPer.type == PersonType::tea)
	{
		Teacher ori = *(Teacher*)&oriPer;
		Teacher newP = Teacher(ori);
		return newP;
	}
	else
	{
		Person newP = Person(oriPer);
		return newP;
	}
}

Teacher::Teacher()
{
	this->type = PersonType::tea;
}
Teacher::Teacher(const Teacher& src):Person(src),
school(src.school)
{
}
Teacher::~Teacher()
{
}
School::School()
{
	this->teacherList = new vector<Teacher>();
}

两个类中,teacher类继承person类,clone函数通过返回引用,可以返回对象的指针:

void TestClone()
{
    Teacher p2;
    p2.age = 20;
    p2.name =3;
    p2.school = 4;

    Person& p3 = p2.Clone(p2);

    
    std::cout << "P2地址:" << (int)&p2 << endl;
    std::cout << "P3地址:" << (int)&p3 << endl;

    Teacher p4 = *(Teacher*)(&p3);
    std::cout << "P4地址:" << (int)&p3 << endl;
    std::cout << "P4school:" << p4.school << endl;

}

通过以下
Teacher p4 = (Teacher)(&p3);
指针格式转换,可以转换数据格式
得到以下结果:

P2地址:577763184
P3地址:577763200
P4地址:577763200
P4school:4

说明数据格式转换成功;

###类中的成员对象在堆和栈中的区分:

测试以下两个函数

void TestCloneAdress01()
{
    Teacher p2;
    p2.age = 20;
    p2.name = 3;
    p2.school = 4;
    School school;

    school.teacherList->push_back(p2);
    std::cout << "ori teacher addres:" << (int)&p2 << endl;
    std::cout << "school adress:" << (int)&school << endl;
    std::cout << "teacher list adress:" << (int)school.teacherList << endl;
    std::cout << "teacher adress:" << (int)&school.teacherList->at(0) << endl;
}
void TestCloneAdress02()
{
    Teacher p4;
    p4.age = 210;
    p4.name = 33;
    p4.school = 43;
    School* school= new School();

    school->teacherList->push_back(p4);

    std::cout << "ori teacher addres:" << (int)&p4 << endl;
    std::cout << "school adress:" << (int)school << endl;
    std::cout << "teacher list adress:" << (int)school->teacherList << endl;
    std::cout << "teacher adress:" << (int)&school->teacherList->at(0) << endl;
}

得到以下结果:

ori teacher addres:-783090680
school adress:-783090688
teacher list adress:1398148368
teacher adress:1398149200
**************************************************
ori teacher addres:-783090680
school adress:1398146448
teacher list adress:1398148208
teacher adress:1398149296

可以发现,school类中的teacher是开辟在堆中的,因此它的子成员也都存在于堆中,
原始定义的数据通过数据的传递复制到堆中

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值