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 ...
随机推荐
- 用IDEA写出第一个java web
今天学习到如何创建新的java web,笔者使用的是IDEA,以下有详细的参考链接,如下: 参考链接:https://blog.csdn.net/zhdkong/article/details/789 ...
- Spring JdbcTemplate详解及项目中的运用
1.Spring对不同的持久化支持: Spring为各种支持的持久化技术,都提供了简单操作的模板和回调 ORM持久化技术 模板类 JDBC org.springframework.jdbc.core. ...
- SpringBoot(1)—启动原理之SpringApplication对象的创建
创建SpringApplication对象 SpringBoot版本为 2.1.1.RELEASE @SpringBootApplication public class SpringbootDemo ...
- EOS 主节点同步
一.从github克隆主网代码仓库 git clone https://github.com/EOSIO/eos --recursive 二.编译与安装EOS环境 cd ~/eos ./eosio_b ...
- python——函数重点总结
参数的分类 形参:位置参数.默认参数.*args.命名关键字参数.**kwargs 实参:位置参数.关键字参数 命名关键字参数:定义在*后面的位置参数和默认参数叫作命名关键字参数:用来限制实参必须以关 ...
- 【Sass初级】嵌套选择器规则
在CSS中,我们都知道所有代码都在一个“根级别”的选择器中,每个CSS的样式声明都写嵌套的话,那意客味需要写很多的代码. 今天我要带领大家进入到Sass的最基本原则中.这就是所谓的“基础规则(Ince ...
- Linux —— gcc编译文件
编译过程 预处理: 作用: 负责展开在源文件重定义的宏 操作: g++ -E 源文件.c -o 目标文件.i 汇编: 作用: 将目标文件生成汇编代码文件 操作: g++ -S 目标文件.i -o 汇编 ...
- POJ-3352-RoadConstruction(边双联通分量,缩点)
链接:https://vjudge.net/problem/POJ-3352#author=0 题意: 给一个无向连通图,至少添加几条边使得去掉图中任意一条边不改变图的连通性(即使得它变为边双连通图) ...
- Codeforces 190C(模拟)
坑点 不记它难解我心头之恨-- WA1:不要读错题Orz,顺序是按它给定的.那就是个类似栈的东西,重点在于输出. 然而我输出很快就模拟对了-- WA2:数据:1 int.我日了不看数据我真的去de模拟 ...
- 转 DataGuard环境搭建 (一主一备一级联)
DataGuard环境搭建 (一主一备一级联) http://blog.itpub.net/30130773/viewspace-2116985/ 1.--------- primary_role / ...