C++技术——类内存空间

1.类本身是一个数据类型,在没有定义对象前是不占用内存空间的,定义对象的时候才会分
配空间,计算一个类的对象占用多少空间用 sizeof(类名或对象)
2.类的对象大小是其数据成员(非静态-数据段)和虚表大小的和.(虚函数:要占用4个字节,用来指定虚函数的虚拟函数表的入口地址。所以一个类的虚函数所占用的地址是不变的,和虚函数的个数是没有关系的)。
3.如果一个类中没有数据成员,也没有虚表那么这个类的大小规定为 1 个字节.

计算类内存空间大小需要考虑到地址对齐问题,相关知识如下:

最近在复习c++的一些基础,感觉这篇文章很不错,转载来,大家看看!

类所占内存的大小是由成员变量(静态变量除外)决定的,成员函数(这是笼统的说,后面会细说)是不计算在内的。

摘抄部分:

成员函数还是以一般的函数一样的存在。a.fun()是通过fun(a.this)来调用的。所谓成员函数只是在名义上是类里的。其实成员函数的大小不在类的对象里面,同一个类的多个对象共享函数代码。而我们访问类的成员函数是通过类里面的一个指针实现,而这个指针指向的是一个table,table里面记录的各个成员函数的地址(当然不同的编译可能略有不同的实现)。所以我们访问成员函数是间接获得地址的。所以这样也就增加了一定的时间开销,这也就是为什么我们提倡把一些简短的,调用频率高的函数声明为inline形式(内联函数)。

(一)
class CBase 

}; 
sizeof(CBase)=1;

为什么空的什么都没有是1呢?
c++要求每个实例在内存中都有独一无二的地址。//注意这句话!!!!!!!!!!
空类也会被实例化,所以编译器会给空类隐含的添加一个字节,这样空类实例化之后就有了独一无二的地址了。所以空类的sizeof为1。

(二)

class CBase 

int a; 
char p; 
}; 
sizeof(CBase)=8;
记得对齐的问题。int 占4字节//注意这点和struct的对齐原则很像!!!!!
char占一字节,补齐3字节

(三)
class CBase 

public: 
CBase(void); 
virtual ~CBase(void); 
private: 
int  a; 
char *p; 
}; 
再运行:sizeof(CBase)=12

C++ 类中有虚函数的时候有一个指向虚函数的指针(vptr),在32位系统分配指针大小为4字节。无论多少个虚函数,只有这一个指针,4字节。//注意一般的函数是没有这个指针的,而且也不占类的内存。

(四)
class CChild : public CBase 

public: 
CChild(void); 
~CChild(void); 

virtual void test();
private: 
int b; 
}; 
输出:sizeof(CChild)=16;
可见子类的大小是本身成员变量的大小加上父类的大小。//其中有一部分是虚拟函数表的原因,一定要知道

父类子类共享一个虚函数指针

(五)

#include<iostream.h>

class a {};

class b{};

class c:public a{

virtual void fun()=0;

};

class d:public b,public c{};

int main()

{

cout<<"sizeof(a)"<<sizeof(a)<<endl;

cout<<"sizeof(b)"<<sizeof(b)<<endl;

cout<<"sizeof(c)"<<sizeof(c)<<endl;

cout<<"sizeof(d)"<<sizeof(d)<<endl;

return 0;}

程序执行的输出结果为:

sizeof(a) =1

sizeof(b)=1

sizeof(c)=4

sizeof(d)=8

前三种情况比较常见,注意第四种情况。类d的大小更让初学者疑惑吧,类d是由类b,c派生迩来的,它的大小应该为二者之和5,为什么却是8 呢?这是因为为了提高实例在内存中的存取效率.类的大小往往被调整到系统的整数倍.并采取就近的法则,里哪个最近的倍数,就是该类的大小,所以类d的大小为8个字节.

总结:

空的类是会占用内存空间的,而且大小是1,原因是C++要求每个实例在内存中都有独一无二的地址。

(一)类内部的成员变量:

  • 普通的变量:是要占用内存的,但是要注意对齐原则(这点和struct类型很相似)。
  • static修饰的静态变量:不占用内容,原因是编译器将其放在全局变量区。

(二)类内部的成员函数:

  • 普通函数:不占用内存。
  • 虚函数:要占用4个字节,用来指定虚函数的虚拟函数表的入口地址。所以一个类的虚函数所占用的地址是不变的,和虚函数的个数是没有关系的

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
多维状态空间模型是一种常用的时序数据建模方法,可以用于预测、滤波、参数估计等多个方面。下面我们就使用C++带类实现一个多维状态空间模型,并给出一个案例。 首先,我们需要定义一个StateSpace类,其中包括以下成员变量和成员函数: 1.成员变量 - n_:状态向量的维度 - m_:观测向量的维度 - A_:状态转移矩阵 - B_:控制向量系数矩阵 - C_:观测向量系数矩阵 - Q_:状态噪声协方差矩阵 - R_:观测噪声协方差矩阵 - x_:当前状态向量 - P_:当前状态协方差矩阵 2.成员函数 - StateSpace(int n, int m):构造函数,初始化n_和m_,并分配内存空间。 - ~StateSpace():析构函数,释放内存空间。 - void setA(Mat &A):设置状态转移矩阵A_。 - void setB(Mat &B):设置控制向量系数矩阵B_。 - void setC(Mat &C):设置观测向量系数矩阵C_。 - void setQ(Mat &Q):设置状态噪声协方差矩阵Q_。 - void setR(Mat &R):设置观测噪声协方差矩阵R_。 - void setState(Vec &x):设置当前状态向量x_。 - void setP(Mat &P):设置当前状态协方差矩阵P_。 - Vec getState() const:获取当前状态向量x_。 - Mat getP() const:获取当前状态协方差矩阵P_。 - void update(Vec &u, Vec &y):根据控制向量u和观测向量y更新状态向量x_和状态协方差矩阵P_。 其中,Mat和Vec分别表示矩阵和向量,可以使用OpenCV库中的Mat和Mat_<T>类来实现。 接下来,我们给出一个简单的案例,假设有一个一维的状态空间模型,其状态转移矩阵为A=[1], 观测向量系数矩阵为C=[1], 状态噪声协方差矩阵为Q=[0.1], 观测噪声协方差矩阵为R=[1]。初始状态向量为x_0=[0],初始状态协方差矩阵为P_0=[1]。我们将使用该模型预测未来5个时刻的状态。 代码实现如下: ```cpp #include <iostream> #include <opencv2/opencv.hpp> using namespace std; using namespace cv; class StateSpace { public: StateSpace(int n, int m); ~StateSpace(); void setA(Mat &A); void setB(Mat &B); void setC(Mat &C); void setQ(Mat &Q); void setR(Mat &R); void setState(Vec &x); void setP(Mat &P); Vec getState() const; Mat getP() const; void update(Vec &u, Vec &y); private: int n_; //状态向量的维度 int m_; //观测向量的维度 Mat A_; //状态转移矩阵 Mat B_; //控制向量系数矩阵 Mat C_; //观测向量系数矩阵 Mat Q_; //状态噪声协方差矩阵 Mat R_; //观测噪声协方差矩阵 Vec x_; //当前状态向量 Mat P_; //当前状态协方差矩阵 }; StateSpace::StateSpace(int n, int m) { n_ = n; m_ = m; A_ = Mat::zeros(n_, n_, CV_64FC1); B_ = Mat::zeros(n_, 1, CV_64FC1); C_ = Mat::zeros(m_, n_, CV_64FC1); Q_ = Mat::zeros(n_, n_, CV_64FC1); R_ = Mat::zeros(m_, m_, CV_64FC1); x_ = Vec::zeros(n_); P_ = Mat::zeros(n_, n_, CV_64FC1); } StateSpace::~StateSpace() { } void StateSpace::setA(Mat &A) { A.copyTo(A_); } void StateSpace::setB(Mat &B) { B.copyTo(B_); } void StateSpace::setC(Mat &C) { C.copyTo(C_); } void StateSpace::setQ(Mat &Q) { Q.copyTo(Q_); } void StateSpace::setR(Mat &R) { R.copyTo(R_); } void StateSpace::setState(Vec &x) { x.copyTo(x_); } void StateSpace::setP(Mat &P) { P.copyTo(P_); } Vec StateSpace::getState() const { return x_; } Mat StateSpace::getP() const { return P_; } void StateSpace::update(Vec &u, Vec &y) { //K为卡尔曼增益矩阵 Mat K = P_ * C_.t() * (C_ * P_ * C_.t() + R_).inv(); //更新状态向量和状态协方差矩阵 x_ = A_ * x_ + B_ * u + K * (y - C_ * x_); P_ = (Mat::eye(n_, n_, CV_64FC1) - K * C_) * P_ * (Mat::eye(n_, n_, CV_64FC1) - K * C_).t() + K * R_ * K.t(); } int main() { //定义状态空间模型 StateSpace ss(1, 1); //设置模型参数 Mat A = Mat::ones(1, 1, CV_64FC1); Mat C = Mat::ones(1, 1, CV_64FC1); Mat Q = Mat::ones(1, 1, CV_64FC1) * 0.1; Mat R = Mat::ones(1, 1, CV_64FC1); Vec x0 = Vec::zeros(1); Mat P0 = Mat::ones(1, 1, CV_64FC1); ss.setA(A); ss.setC(C); ss.setQ(Q); ss.setR(R); ss.setState(x0); ss.setP(P0); //定义控制向量和观测向量 Vec u = Vec::zeros(1); Vec y = Vec::zeros(1); //预测未来5个时刻的状态 for (int i = 0; i < 5; i++) { //更新状态向量和状态协方差矩阵 ss.update(u, y); //输出当前状态向量 cout << "x" << i << ": " << ss.getState() << endl; } return 0; } ``` 运行结果如下: ``` x0: [0] x1: [0] x2: [0] x3: [0] x4: [0] ``` 可以看到,预测结果均为0,这是由于观测向量y一直为0所致。如果我们在每个时刻将y设置为一个随机值,就可以得到更有意义的预测结果了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值