C++成员变量与函数内存分配
关于结构体和C++类的内存地址问题
C++类是由结构体发展得来的,所以他们的成员变量(C语言的结构体只有成员变量)的内存分配机制是一样的。下面我们以类来说明问题,如果类的问题通了,结构体也也就没问题啦。 类分为成员变量和成员函数,我们先来讨论成员变量。 一个类对象的地址就是类所包含的这一片内存空间的首地址,这个首地址也就对应具体某一个成员变量的地址。(在定义类对象的同时这些成员变量也就被定义了)我们来以一段代码说明问题:
class K
{
public:
K(){k = 12;}
~K(){}
int k;
}; K kTemp;
printf("%d--%d\n",&kTemp,&kTemp.k);
printf("%d--%d\n",sizeof(K),sizeof(kTemp.k));
int *i = (int*)(&kTemp);
int w = *i;
printf("%d\n",w);
运行上面的代码,结果如下:
1310588--1310588
4--4
12
很明显,类的内存大小和其唯一的成员变量的内存大小是一致的。内存地址也是一致的。他们甚至可以相互转换。换成结构体结果也是一样。。
那么成员函数又如何?上面得代码就好像类没有任何成员函数一样,根本说明不了问题。 呵呵
,所有的函数都是存放在代码区的,不管是全局函数,还是成员函数。要是成员函数占用类的对象空间,那么将是多么可怕的事情:定义一次类对象就有成员函数占用一段空间。 我们再来补充一下静态成员函数的存放问题吧:
静态成员函数与一般成员函数的唯一区别就是没有this指针,因此不能访问非静态数据成员,就像我前面提到的,所有函数都存放在代码区,静态函数也不例外。所有有人一看到 static 这个单词就主观的认为是存放在全局数据区,那是不对的
c++是一种面向对象的编程语言,它向下保持了对c的兼容,同时也允许程序员能够自由的操控内存,虽然会带来一些问题,但这不是我们要探讨的问题,略过不表。类是对某种对象的定义,包含变量和方法,也可以理解为现实生活中一类具有共同特征的事务的抽象,他是面向对象语言的基础。所以类是不占有内存的,可是如果类生成实例那么将会在内存中分配一块内存来存储这个类。
类的实例在内存中是如何分配内存的,有什么需要我们注意的,下面将慢慢到来。
比如下面一个类:
class A
{};
从形式上看,它似乎什么有没有,事实上它不止隐含了一个构造函数和一个析构函数,还有一些操作符重载函数,比如“=”。如果类A被实例话,如A a;在内存会占据多大的空间呢?有人可能会说4,也有人会说0,还有人会说1,说1的就对了,为什么会是1呢?原因有很多,如果我们定义一个数组A b[10];如果上面是0,这样的局面将会很尴尬,所以A这样一个空类,编译器会给它一个字节来填充。
增加一个变量,(字节对齐默认都是4)
class A
{
public:
int i;
}
类A的实例将占据4个字节的内存,sizeof(A) = 4
变量i 的初值被编译器指定位0xcdcdcdcd。
再增加一个变量,
class A
{
public:
int i;
int l;
}
此时按照变量生命的先后顺序,i被放在低地址上,l紧随其后。
实例占用8个字节,sizeof(A) = 4*2 = 8
如果类里面含有函数:
class A
{
public:
int i;
int l;
int add(int x,int y){return (x+y);}
};
有些人可能会说类的大小是12,事实上sizeof(A) = 8;
为什么会这样,这是因为sizeof访问的程序的数据段,而函数地址则被保存在代码段内,所以最后的结果是8.
再看下面这个情况
class A
{
public:
int i;
int l;
static int s;
int add(int x,int y){return (x+y)};
};
此时sizeof(A)大小仍为8,这里留给读者去思考为什么?(^-^)。
当类里面含有虚函数时,情况会如何呢?
class A
{
public:
int i;
int l;
static int s;
virtual void Say(){};
int add(int x,int y){return (x+y)};
};
因为含有虚函数,所以类里面将含有一个虚指针vptr,指向该类的虚表vtbl,一个指针占用四字节的地址,所以sizeof(A) = 12
虚指针放在类实例地址的最低位置,
比如 A *a = new A;
我们可以这样给变量i赋值
int *p = (int *)a;
p++;
*p = 1;//把i的值赋为1.
如果类作为派生类,内存将如何分配呢?
这种情况虽然有些复杂,但并不是说不好理解。
他有多少个父类每个父类的大小加起来在加上自身就是sizeof的大小。
C++成员变量与函数内存分配的更多相关文章
- Java中的成员初始化顺序和内存分配过程
Java中的成员初始化顺序和内存分配过程 原帖是这样描述的: http://java.dzone.com/articles/java-object-initialization?utm_source= ...
- C语言中 struct成员变量顺序对内存的占用
在C语言的结构体中,是会按照其变量类型来进行分配内存大小的.但是对于不同的编译器,结果是不同的,在VC++6.0中是怎么个分配情况呢?用一下C中的关键字sizeof()来测试下,注意sizeof()不 ...
- C++构造函数和析构函数,以及构造函数特殊成员变量和函数的初始化
body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...
- java中static修改成员变量和函数和其他使用
一.通过static修饰的成员变量初始化只会初始化一次 //静态变量初始化只会初始化一次 public class zuishuai { public static void main(String[ ...
- var声明的成员变量和函数内声明的变量区别
1.函数内部,有var声明的是局部变量,没var的,声明的全局变量. 2.在全局作用域内声明变量时,有var 和没var声明的都是全局变量,是window的属性.通过变量var声明全局对象的属性无法通 ...
- linux C++类中成员变量和函数的使用
1.undefined reference to XXX 问题原因 1)XXX所在的so库等未指定 2)XXX在类中实现的时候没有加上类::函数的格式 2. was not declared in t ...
- C++类内存布局图(成员函数和成员变量分开讨论)
一.成员函数 成员函数可以被看作是类作用域的全局函数,不在对象分配的空间里,只有虚函数才会在类对象里有一个指针,存放虚函数的地址等相关信息. 成员函数的地址,编译期就已确定,并静态绑定或动态的绑定在对 ...
- c/c++ 类成员变量,成员函数的存储方式,以及this指针在c++中的作用
c/c++ 类成员变量,成员函数的存储方式,以及this指针在c++中的作用 c++不会像上图那样为每一个对象的成员变量和成员函数开辟内存空间, 而是像下图那样,只为每一个对象的成员变量开辟空间.成员 ...
- 【转】C++ const成员变量和成员函数(常成员函数)
转:http://c.biancheng.net/view/2230.html 在类中,如果你不希望某些数据被修改,可以使用const关键字加以限定.const 可以用来修饰成员变量和成员函数. co ...
随机推荐
- [HDU 3336]Count the String[kmp][DP]
题意: 求一个字符串的所有前缀串的匹配次数之和. 思路: 首先仔细思考: 前缀串匹配. n个位置, 以每一个位置为结尾, 就可以得到对应的一个前缀串. 对于一个前缀串, 我们需要计算它的匹配次数. k ...
- 宣布发布 Windows Azure ExpressRoute,宣告与 Level 3 建立全新的合作伙伴关系并推出关于其他 Azure 服务令人振奋的更新
在我们与世界各地的客户和合作伙伴交谈时,总会听到他们说,希望找到一个提供商帮助他们最大限度地发挥内部部署投资的作用并且能够利用云的灵活性.这是我们构建混合云策略和云操作系统愿景的基本原则.本着我 ...
- Flex4 设置combobox选项不可编辑
近日做数据的增删改查,使用的flex4的ComboBox控件---> flex4中ComboBox其实就是TextInput的叠加 flex3中ComboBox其实就是Label的叠加 开始是使 ...
- QT renered html for js
voidMainWindow::on_pushButton_clicked() { QStringurl="http://www.baidu.com"; url="htt ...
- TEX Quotes(字符串,水)
TEX Quotes Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 9674 Accepted: 5073 Descri ...
- 浅谈JDBC(一)
一.JDBC技术引言 1.什么是JDBC技术 提供了一套接口规范,利用java代码进行数据库操作. 2.JDBC技术的核心思想 对于程序员来说,代码访问数据库分为三个步骤:1.通过数据库的账号密码.2 ...
- 在Eclipse中使用JDBC访问MySQL数据库的配置方法
在Eclipse中使用JDBC访问MySQL数据库的配置方法 分类: DATABASE 数据结构与算法2009-10-10 16:37 5313人阅读 评论(10) 收藏 举报 jdbcmysql数据 ...
- Django admin究竟要怎么写才优雅
比如在Django admin 注册models时,会用到. 对于APP里自带的models,可以使用这种方式注册. from django.contrib import admin # Regist ...
- The reference to entity "characterEncoding" must end with the ';' delimiter
数据源配置时加上编码转换格式后出问题了: The reference to entity "characterEncoding" must end with the ';' del ...
- ios7下二维码功能的实现
苹果公司升级到IOS7后自己的PassBook自带二维码扫描功能,所以现在使用二维码功能不需要在借助第三方库了 使用前请先导入AVFoundation.frameWork // // YHQView ...