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 ...
随机推荐
- spring框架_AOP和注解
1.什么是AOP :全称是Aspect Oriented Programming即:面向切面编程. 简单来说它就是把我们程序重复的代码抽取出来,在需要执行的时候,使用动态代理的技术,在不修改源码的基础 ...
- js异步加载和按需加载
function loadScript(url,callback){ var script = document.creatElement("script"); script.ty ...
- 紫书140例题6-2 铁轨&&UVa514
某城市有一个火车站,铁轨铺设如图6-1所示.有n节车厢从A方向驶入车站,按进站顺序编号为1~n.你的任务是判断是否能让它们按照某种特定的顺序进入B方向的铁轨,并驶出车站.例如,出栈顺序(5 4 1 2 ...
- 我所接触到的JWT
名称:JWT--->Json Web Token 用途:客户端请求服务端API时的认证方式之一 用法: 优点: 体积小(一串字符串),因而传输速度快 支持跨域验证,多应用于单点登录 传输方式多样 ...
- Net Core -- 配置Kestrel端口
Net Core -- 配置Kestrel端口 Kestrel介绍 在Asp.Net Core中,我们的web application 其实是运行在Kestrel服务上,它是一个基于libuv开源的跨 ...
- Middleware-请求管道的构成
Middleware-请求管道的构成 在 ASP.NET 中,我们知道,它有一个面向切面的请求管道,有19个主要的事件构成,能够让我们进行灵活的扩展.通常是在 web.config 中通过注册 Htt ...
- 定时任务crontab 详解
cron 是一个可以用来根据时间.日期.月份.星期的组合来调度对重复任务的执行的守护进程. cron 假定系统持续运行.如果当某任务被调度时系统不在运行,该任务就不会被执行. 要使用 cron 服务, ...
- HDU 1024 A - Max Sum Plus Plus DP + 滚动数组
http://acm.hdu.edu.cn/showproblem.php?pid=1024 刚开始的时候没看懂题目,以为一定要把那n个数字分成m对,然后求m对中和值最大的那对 但是不是,题目说的只是 ...
- windows黑窗口关于java程序的常用命令
1.启动java程序 我要运行:E:\code\nhtask下的ElectricEye-0.0.1-SNAPSHOT.jar程序 #切换到程序目录cd E:\code\nhtaskE: java -j ...
- Random类、ThreadLocalRandom类
Random和ThreadLocalRandom类均用于生成伪随机数. Random的构造函数: Random() 默认以系统当前时间为种子,相当于Random(System.currentT ...