stack与heap、new的内存分配、static对象。(effective c++ 04)
阅读effective c++ 04 (30页) 提到的static对象和堆与栈对象。“不同编译单元内定义的non-local static对象”。
了解一下。
目录
1.動態分配所得的內存塊 (memory block), in VC
3.array new 一定要搭配 array delete
2.两个编译单元中的non-local static object相互引用
stack与heap
1.Stack
存在於某作用域 (scope) 的一塊內存空間(memory space)。例如當你調用函數,函數本身即會形成一個 stack 用來放置它所接收的參數,以及返回地址。在函數本體 (function body) 內聲明的任何變量,其所使用的內存塊都取自上述 stack。
2.Heap 或謂 system heap
指由操作系統提供的一塊 global 內存空間,程序可動態分配 (dynamic allocated) 從某中獲得若干區塊 (blocks)。
3.例子
class Complex { … };
...
{
Complex c1(1,2);
Complex* p = new Complex(3);
}
1.构造函数型 (stack)
c1 所佔用的空間來自 stack。
2.new型 (heap 動態分配)
Complex(3) 是個臨時對象,其所佔用的空間乃是以 new 自 heap 動態分配而得,並由 p 指向。
4.构造函数型 (stack)
1.stack objects 的生命期
class Complex { ... };
...
{
Complex c1(1,2);
}
c1 便是所謂 stack object,其生命在作用域 (scope) 結束之際結束。
這種作用域內的 object,又稱為 auto object,因為它會被「自動」清理。
2.static local objects 的生命期
class Complex { … };
...
{
static Complex c2(1,2);
}
c2 便是所謂 static object,其生命在作用域 (scope)結束之後仍然存在,直到整個程序結束。
3.global objects 的生命期
class Complex { … };
...
Complex c3(1,2);
int main()
{
...
}
c3 便是所謂 global object,其生命在整個程序結束之後才結束。你也可以把它視為一種 static object,其作用域是「整個程序」。
5.new型 (heap 動態分配)
heap objects 的生命期
class Complex { … };
...
{
Complex* p = new Complex;
...
delete p;
}
P 所指的便是 heap object,其生命在它被 deleted 之際結束。
class Complex { … };
...
{
Complex* p = new Complex;
}
以上出現內存洩漏 (memory leak),因為當作用域結束,p 所指的 heap object 仍然存在,但指針 p 的生命卻結束了,作用域之外再也看不到 p (也就沒機會 delete p)。
关于new型的内存分配
1.自定义类class型
1.new:先分配 memory, 再調用 ctor
Complex* pc = new Complex(1,2);
編譯器轉化為
Complex *pc;
void* mem = operator new( sizeof(Complex) ); //分配內存
pc = static_cast<Complex*>(mem); //轉型
pc->Complex::Complex(1,2); //構造函數
2.delete:先調用 dtor, 再釋放 memory
Complex* pc = new Complex(1,2);
...
delete pc;
編譯器轉化為
Complex::~Complex(pc); // 析構函數
operator delete(pc); // 釋放內存。其內部調用 free(pc)
2.String*型
1.new:先分配 memory, 再調用 ctor
String* ps = new String("Hello String("Hello");
編譯器轉化為
String* ps;
void* mem = operator new( sizeof(String) ); //分配內存
ps = static_cast<String*>(mem); //轉型
ps->String::String("Hello"); //構造函數
2.delete:先調用 dtor, 再釋放 memory
String* ps = new String("Hello");
...
delete ps;
編譯器轉化為
String::~String(ps); // 析構函數
operator delete(ps); // 釋放內存
3.动态分配
1.動態分配所得的內存塊 (memory block), in VC

2.動態分配所得的 array

3.array new 一定要搭配 array delete
String* p = new String[3];
...
delete[] p; //喚起3次dtor
String* p = new String[3];
...
delete p; //喚起1次dtor
static对象
C++中的static对象是指存储区不属于stack和heap、"寿命"从被构造出来直至程序结束为止的对象,程序结束时static对象会自动销毁。
这些对象包括全局对象,定义于namespace作用域的对象,在class、function以及file作用域中被声明为static的对象。
其中,函数内的static对象称为local static 对象,而其它static对象称为non-local static对象。
1.何时被初始化(构造)
1.non-local static object
全局对象,定义于namespace作用域的对象,在class及file作用域中被声明为static,函数之外的对象。
生命期起始时间:在main()函数调用之前被构造初始化。
生命期终止时间:在main()函数结束后自动被析构。
2.local static object
指函数中用static修饰符修饰的object。
生命期起始时间:在函数第一次调用时构造初始化。
生命期终止时间:在main()函数结束后自动被析构。
2.两个编译单元中的non-local static object相互引用
注意:在同一个文件或不同编译单元(不同文件)中,如果存在多个non-local static object,它们都是在主函数调用之前被构造的,但是它们之间的构造顺序时不定的。即对编译器来说,静态成员对象之间的初始化顺序和析构顺序是一个未定义的行为。
因此,不能用某个non-local static object去初始化non-local static object,无论这两个non-local static object在不在同一个编译单元中。
class FileSystem
{
public: …
std::size_t numDisks() const;
};
extern FileSystem tfs;
//另一编译单元
class Directory
{
public:
Directory(params);
};
Directory::Directory(params)
{
std::size_t disks = tfs.numDisks();//使用另一个编译单元的静态变量
}
Directory tempDir (params);
由于编译器没有定义non-local static object之间的构造顺序,所以有可能类tfs还没有被构造,所以程序可能会报错。
3.解决方法
用local static对象替换non-local static对象。
C++保证,函数内的local static 对象会在该函数被调用期间,首次遇上该对象定义式时被初始化。
class FileSystem {…};
FileSystem& tfs()
{
static FileSystem fs;
return fs;
}
//另一编译单元
class Directory {…};
Directory::Directory (params)
{
std::size_t disks = tfs().numDisks();//执行函数tfs时,对象fs肯定会被构造。
};
Directory& tempDir()
{
static Directory td;
return td;
}
stack与heap、new的内存分配、static对象。(effective c++ 04)的更多相关文章
- C++内存分配与对象构造的分离
在C++中,我们基本用new(delete)操作符分配(释放)内存.new操作符为特定类型分配内存,并在新分配的内存中构造该类型的一个对象.new表达式自动运行合适的构造函数来初始化每个动态分配的类类 ...
- JVM的stack和heap,JVM内存模型,垃圾回收策略,分代收集,增量收集
(转自:http://my.oschina.net/u/436879/blog/85478) 在JVM中,内存分为两个部分,Stack(栈)和Heap(堆),这里,我们从JVM的内存管理原理的角度来认 ...
- Java虚拟机创建对象的内存分配以及对象的内存布局
本博文知识参考周志明<深入理解Java虚拟机> Java虚拟机在创建对象使如果进行内存分配: 1.指针碰撞 2.空闲列表 Java在多线程情况下创建对象的内存分配: Java完成对象内存分 ...
- JAVA基础-栈与堆,static、final修饰符、内部类和Java内存分配
Java栈与堆 堆:顺序随意 栈:后进先出(Last-in/First-Out). Java的堆是一个运行时数据区,类的对象从中分配空间.这些对象通过new.newarray.anewarray和mu ...
- JVM性能优化系列-(2) 垃圾收集器与内存分配策略
2. 垃圾收集器与内存分配策略 垃圾收集(Garbage Collection, GC)是JVM实现里非常重要的一环,JVM成熟的内存动态分配与回收技术使Java(当然还有其他运行在JVM上的语言,如 ...
- Netty 中的内存分配浅析-数据容器
本篇接续前一篇继续讲 Netty 中的内存分配.上一篇 先简单做一下回顾: Netty 为了更高效的管理内存,自己实现了一套内存管理的逻辑,借鉴 jemalloc 的思想实现了一套池化内存管理的思路: ...
- linux环境内存分配原理 mallocinfo
Linux的虚拟内存管理有几个关键概念: Linux 虚拟地址空间如何分布?malloc和free是如何分配和释放内存?如何查看堆内内存的碎片情况?既然堆内内存brk和sbrk不能直接释放,为什么不全 ...
- 【转】linux环境内存分配原理 malloc info
Linux的虚拟内存管理有几个关键概念: Linux 虚拟地址空间如何分布?malloc和free是如何分配和释放内存?如何查看堆内内存的碎片情况?既然堆内内存brk和sbrk不能直接释放,为什么不全 ...
- linux环境内存分配原理 mallocinfo【转】
转自:http://www.cnblogs.com/dongzhiquan/p/5621906.html Linux的虚拟内存管理有几个关键概念: Linux 虚拟地址空间如何分布?malloc和fr ...
- Android O Bitmap 内存分配
我们知道,一般认为在Android进程的内存模型中,heap分为两部分,一部分是native heap,一部分是Dalvik heap(实际上也是native heap的一部分). Andro ...
随机推荐
- 手工sql注入判断是否存在注入点
1.加入单引号 ’提交,结果:如果出现错误提示,则该网站可能就存在注入漏洞.2.数字型判断是否有注入;语句:and 1=1 ;and 1=2 (经典).' and '1'=1(字符型)结果:分别返回不 ...
- 如何在 Laravel 中 “规范” 的开发验证码发送功能
什么是ThinkSNS ? ThinkSNS(简称TS),一款全平台综合性社交系统,为国内外大中小企业和创业者提供社会化软件研发及技术解决方案,目前最新版本为ThinkSNS+(简称TS+).Thin ...
- VS 小插件 之 编辑器背景图片
一.引言 不知道标题的名字我描述的是否正确哈,其实就是用VS写代码的时候,背景一般都是纯白 或者 纯黑(看主题而定),那么我前段时间发现 只需要一个VS插件,居然可以给VS设置背景图片,甚至还可以循环 ...
- render函数和redirect函数的区别+反向解析
render函数和redirect函数的区别+反向解析 1.视图函数:一定是要包含两个对象的(render源码里面有HttpResponse对象) request对象:----->所有的请求 ...
- Django之Form自定义验证规则
1.数据源无法时时更新,有两种方法 方式一:重构构造方法(推荐) 方法一:重构构造方法(推荐) class ClassesForm(Form): name = fields.CharField( re ...
- Codeforces 1C(外接圆与正多边形)
要点 各点肯定都在外接圆上,边越多越接近圆面积,所以要最小面积应当取可能的最少边数. 给三角形求外接圆半径公式:\(R=\frac{abc}{4S}\). 三个角度对应的圆心角取gcd即是要求的正多边 ...
- Netty(2)Echo
上节介绍的是discard协议,即不给客户端返回消息.本节主要说下,echo协议,即服务端收到消息后原样返回给客户端. 为了实现此需求,只需要在DiscardServerHandler中重写chann ...
- 简易的开发框架(微服务) Asp.Net Core 2.0
Asp.Net Core 2.0 + Mysql Orm + Ioc + Redis + AOP + RabbitMQ + Etcd + Autofac + Swagger 基础框架: https ...
- 关于Memcache的连接
addServer 在说Memcache的长连接(pconnect)和短连接(connect)之前要先说说Memcache的addServer,Memcache的addServer是增加一个服务器到连 ...
- display:none和visibility:hidden v-show和v-if的区别
隐藏元素display:none 和 visibility:hidden的区别visibility:hidden可以隐藏某个元素,但是隐藏的元素仍要占据空间,仍要影响布局display:none不会占 ...