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是开辟在堆中的,因此它的子成员也都存在于堆中,
原始定义的数据通过数据的传递复制到堆中