对象大小:
对象占据一定大小的内存空间。总的来说,对象在内存中是以结构形式(只包括非static数据成员)存储在数据段或堆中,类对象的大小(sizeof)一般是类中所有非static成员的大小之和。在程序编译期间,就已经为static变量在静态存储区域分配了内存空间,并且这块内存在程序的整个运行期间都存在。而类中的成员函数存在于代码段中,不管多少个对象都只有一个副本。
1、C++将类中的引用成员当成“指针”来维护,占据4个内存字节。(linux64位操作系统是8)
2、如果类中有虚函数时,虚析构函数除外,还会额外分配一个指针用来指向 ,因此,这个时候对象的大小还要加4。
3、指针成员和引用成员属于“最宽基本数据类型”的考虑范畴。
成员变量和成员函数内存中存放方式
#include <iostream>
using namespace std;
//64位操作系统默认对齐系数是8 //sizeof(cex): 56
#pragma pack(4)
class cex
{
private:
int a;
//int型,在一般系统上占据4个内存字节 4
char b;
//char型,占1个内存字节 1
float c;
//单精度浮点型,占4个内存字节4+1+3+4=12
double d;
//double型,占8个内存字节 12+8=20 ; 64位操作系统默认对齐系数8 这里就是12+4+8=24
short e[5];
//short型数组,每个元素占2个内存字节2*5=10 ; 20+10=30; 24+10=34
char & f;
//引用,当成指针维护,8个内存字节 30+2+8=40 34+6+8=48
double & g;
//引用,当成指针维护,8个内存字节 40+8=48 48+8=56
static int h;
//static成员,公共内存,不影响单个对象的大小 0
public:
cex():f(b), g(d) //构造函数,引用成员必须在初始化表中初始化
{
}
void print() //成员函数的定义,普通成员函数不影响对象大小
{
cout << "Hello" << endl;
}
};
|
//min(4,8) 按4对齐,48刚好是4的倍数
//min(8,8) 56刚好是8的倍数
int cex::h = 0; //static成员的初始化
int main()
{
cex c;
cout << "sizeof(cex): " << sizeof(cex) << endl;
return 0;
}
//sizeof(cex): 48
|
对象数组的声明:
类名 数组名[对象个数];
这种格式会自动调用无参或所有参数都有缺省值的构造函数,类定义要符合该要求,否则编译报错。
对象数组的初始化:
可以在声明时初始化
对于point(int ix,int iy){}这种没有缺省参数值的构造函数:
point pt[2]={point(1,2), point(3,4)}; //#1 正确
point pt[ ]={point(1,2), point(3,4)}; //#2 正确
point pt[5]={point(1,2), point(3,4)}; //#3 错误
//没有写出来的都是采用point()的形式,需要调用无参构造函数
对象动态分配内存:
用new和delete为对象分配动态存储区
此时,如果写了析构函数,并且是用new动态分配数组的内存空间的话,那么还会多开辟4个字节的内存空间,用来存放分配数组的大小。这样析构函数才知道要释放多大的内存空间
#include <iostream>
using namespace std;
class Point
{
private:
int _ix;
int _iy;
public:
Point()
: _ix(0)
, _iy(0)
{
cout << "Point()" << endl;
}
Point(int ix, int iy)
: _ix(ix)
, _iy(iy)
{
cout << "Point(int,int)" << endl;
}
void print()
{
cout << "(" << _ix<< "," << _iy<<")"<<endl;
}
~Point()
{
cout << "~Point()" << endl;
}
};
|
int main(void)
{
Point arr[2];
cout<<endl;
Point(5, 6); //匿名对象-->临时对象,创建完立马撤销
cout<<endl;
Point arr2[3] = {Point(1, 2), Point(3, 4)};
arr2[0].print();
arr2[1].print();
arr2[2].print();
cout<<endl;
return 0;
}
|
#include <iostream>
#include<stdlib.h>
using namespace std;
class point
{
private: //private数据成员列表
int x;
int y;
public:
point(int xp=0,int yp=0) //构造函数,带缺省参数值
{
x=xp;
y=yp;
cout<<"point(int,int)"<<endl;
}
~point() //析构函数
{
cout<<"~point()"<<endl;
}
void print() //成员函数,类内部实现
{
cout<<"x: "<<x<<", y: "<<y<<endl;
}
};
|
int main()
{
point* p = new point(4,5); //动态申请一块内存,存储point类对象,并将地址赋值给point型指针p
p->print(); //使用指针加->调用成员函数
delete p; //释放动态申请的内存,防止内存泄露
p=NULL; //养成良好习惯,防止野指针
point *pp = new point[3]; //此时你会发现分配了28个字节的内存空间,多出的最开始的4个字节的内存空间,存放3
pp[0] = point(1,2); //只能这样初始化
pp[1] = point(3,4);
pp[2] = point(5,6);
delete[] pp;
return 0;
}
|