c++ [wrong]simple "Garbage Collector"
In fact, Ptr alone can accomplish the task mentioned below.
Implementation see Ptr.h, main2.cpp. In C++11, we also have a better choice: std::shared_ptr (as you can see in main3.cpp).
main2.cpp
#include "Ptr.h" #include <iostream> using namespace std; class Box
{
public:
void dosomething() { cout << "Box dosomething" << endl; }
Box() { cout << "Box cons" << endl; }
~Box() { cout << "Box des" << endl; }
}; Ptr<Box> global; Ptr<Box> func() {
Ptr<Box> pb(new Box());
return pb;
} void call(Ptr<Box> ptr)
{
if(ptr)
ptr->dosomething();
else
cout << "ptr is null" << endl;
} int main()
{
Ptr<Box> p = func();
p->dosomething();
(*p).dosomething();
Ptr<Box> p2 = p;
call(p2);
p2.reset();
cout << "after p2.reset" << endl;
global = p;
p.reset();
call(p);
(*global).dosomething();
global.reset();
cout << "after global.reset" << endl;
return ;
}
Ptr.h
#ifndef PTR_H
#define PTR_H #include <cstddef> template <typename TYPE>
class Ptr { public:
void reset()
{
dec_use();
}
Ptr& operator=(const Ptr<TYPE> ©)
{
dec_use();
obj = copy.obj;
use_count = copy.use_count;
if (use_count) ++*use_count;
return *this;
}
TYPE* operator->() { return obj; }
TYPE& operator*() { return *obj; }
const TYPE* operator->() const { return obj; }
const TYPE& operator*() const { return *obj; }
operator bool() const { return (obj != NULL); } Ptr(): obj(NULL), use_count(NULL) {}
Ptr(TYPE *obj_): obj(obj_), use_count(new int()) {}
Ptr(const Ptr ©): obj(NULL), use_count(NULL)
{
obj = copy.obj;
use_count = copy.use_count;
if (use_count) ++*use_count;
}
~Ptr()
{
dec_use();
}
private:
void dec_use() // decrease use_count
{
if (use_count != NULL) {
if( --*use_count == ) {
delete obj;
delete use_count;
}
obj = NULL;
use_count = NULL;
}
}
TYPE *obj; // the actual object
int *use_count; // number of Ptr objects point to 'obj'
}; #endif // PTR_H
main3.cpp
#include <memory> #include <iostream> using namespace std; class Box
{
public:
void dosomething() { cout << "Box dosomething" << endl; }
Box() { cout << "Box cons" << endl; }
~Box() { cout << "Box des" << endl; }
}; shared_ptr<Box> global; shared_ptr<Box> func() {
shared_ptr<Box> pb(new Box());
return pb;
} void call(shared_ptr<Box> ptr)
{
if(ptr)
ptr->dosomething();
else
cout << "ptr is null" << endl;
} int main()
{
shared_ptr<Box> p = func();
p->dosomething();
(*p).dosomething();
shared_ptr<Box> p2 = p;
call(p2);
p2.reset();
cout << "after p2.reset" << endl;
global = p;
p.reset();
call(p);
(*global).dosomething();
global.reset();
cout << "after global.reset" << endl;
return ;
}
---------------------------------------- stupidest iead I've ever seen -----------------------------------------
| |
| |
The idea is to create a Ptr type that acts like a reference in Java.
And A Garbage Collector (MemMgr) type that acts like a garbage collector in Java.
Just a toy. :D
Question: why not delete all memory fragments managed by MemMgr in its destructor?
Answer: If you want to delete a piece of memory, you must cast the void* pointer to the exact type of that memory. However, there's no way for a MemMgr to know the type of the memory pieces, because type information is not managed by MemMgr. And you can't use the free function from <cstdlib>. For example, if you write "MemMgr *p = new MemMgr; free(p);" you'll find that the destructor of MemMgr is not called. And As shown in "test.cpp". "free" only works in pair with "malloc" or "realloc" etc functions in <cstdlib>. "delete" should work in pair with "new".
see this question: http://stackoverflow.com/questions/1518711/how-does-free-know-how-much-to-free
test.cpp
#include "MemMgr.h"
#include <cstdlib> int main()
{
MemMgr *p = new MemMgr;
free(p);
return ;
}
main.cpp
#include "MemMgr.h" #include <iostream> using namespace std; class Box
{
public:
void dosomething() { cout << "Box dosomething" << endl; }
Box() { cout << "Box cons" << endl; }
~Box() { cout << "Box des" << endl; }
}; Ptr<Box> global;
MemMgr mgr; Ptr<Box> func() {
Ptr<Box> pb = mgr.regist(new Box());
return pb;
} int main()
{
Ptr<Box> p = func();
p->dosomething();
(*p).dosomething();
Ptr<Box> p2 = p;
p2->dosomething();
cout << "end of main" << endl;
global = p2;
return ;
}
MemMgr.h
#ifndef MEMMGR_H
#define MEMMGR_H #include <map> template <typename TYPE>
class Ptr; /**
MemMgr take the idea of Garbage Collector
from the Java language. It's just much simple
and limited.
*/
class MemMgr
{
template <typename T> friend class Ptr;
private:
typedef unsigned long count;
template <typename T> void login(T* ptr_obj);
template <typename T> void logout(T* ptr_obj);
std::map<void*, count> cmap;
public:
MemMgr();
/**
Client is responsible to ensure obj is in the heap,
and make sure only use Ptr objects rather than ordinary
pointers when manipulating objects managed by MemMgr. Otherwise the behavior of the MemMgr is undefined. If MemMgr is destroyed before any Ptr object managed
by it, all Ptr objects managed by that MemMgr are corrupted
and their behavior is undefined, which eventually leads to
memory leak. So it's crucial to make sure MemMgr is not destroyed
before ALL Ptr objects managed by it are destroyed.
*/
template <typename T> Ptr<T> regist(T *obj);
~MemMgr(); }; /**
Ptr acts like a reference in java.
*/
template <typename TYPE>
class Ptr { friend class MemMgr; public:
Ptr& operator=(const Ptr<TYPE> ©)
{
if(copy) {
logout();
obj = copy.obj;
mgr = copy.mgr;
copy.mgr->login(&obj);
} // else leaves obj and mgr NULL
return *this;
}
TYPE* operator->() { return obj; }
TYPE& operator*() { return *obj; }
const TYPE* operator->() const { return obj; }
const TYPE& operator*() const { return *obj; }
operator bool() const { return ( (obj != NULL) && (mgr != NULL) ); } Ptr(): obj(NULL), mgr(NULL) {}
Ptr(const Ptr ©): obj(NULL), mgr(NULL)
{
if(copy) {
obj = copy.obj;
mgr = copy.mgr;
copy.mgr->login(obj);
}
}
~Ptr()
{
logout();
}
private:
Ptr(TYPE *_obj, MemMgr *_mgr): obj(_obj), mgr(_mgr)
{
mgr->login(obj);
}
void logout() {
if (*this) {
mgr->logout(obj); obj = NULL; mgr = NULL;
}
}
TYPE *obj;
MemMgr *mgr;
}; template <typename T> Ptr<T> MemMgr::regist(T *obj)
{
return Ptr<T>(obj, this);
} template <typename T>
void MemMgr::login(T* ptr_obj)
{
std::map<void*, count>::iterator iter = cmap.find(ptr_obj);
if (iter != cmap.end()) {
++(iter->second);
} else {
cmap.insert(std::pair<void*, count>(ptr_obj, ));
}
} template <typename T>
void MemMgr::logout(T* ptr_obj)
{
std::map<void*, count>::iterator iter = cmap.find(ptr_obj);
if (iter != cmap.end()) {
--(iter->second);
if (iter->second == ) {
T *p = (T*)(iter->first);
delete p;
}
}
} #endif // MEMMGR_H
MemMgr.cpp
#include "MemMgr.h" #include <iostream> using namespace std; MemMgr::MemMgr()
{
cout << "MemMgr cons" << endl;
} MemMgr::~MemMgr()
{
cout << "MemMgr des" << endl;
}
c++ [wrong]simple "Garbage Collector"的更多相关文章
- [GC]一个简单的Garbage Collector的实现
前言: 最近看了google的工程师写的一个非常简单的垃圾收集器,大概200多行C代码,感叹大牛总能够把复杂的东西通过很简单的语言和代码表达出来.为了增加自己的理解,决定把大牛的想法和代码分析一遍,与 ...
- 一个简单的Garbage Collector的实现
一个简单的Garbage Collector的实现 前言: 最近看了google的工程师写的一个非常简单的垃圾收集器,大概200多行C代码,感叹大牛总能够把复杂的东西通过很简单的语言和代码表达出来.为 ...
- AGC027 B - Garbage Collector 枚举/贪心
目录 题目链接 题解 代码 题目链接 AGC027 B - Garbage Collector 题解 对于一组选取组的最优方案为,走到一点,然后顺着路径往回取点 设选取点坐标升序为{a,b,c,d} ...
- New Garbage Collector http://wiki.luajit.org/New-Garbage-Collector
New Garbage Collector http://wiki.luajit.org/New-Garbage-Collector GC Algorithms This is a short ove ...
- agc 027 B - Garbage Collector
B - Garbage Collector https://agc027.contest.atcoder.jp/tasks/agc027_b 题意: x坐标轴上n个垃圾,有一个机器人在从原点,要清扫垃 ...
- Getting Started with the G1 Garbage Collector(译)
原文链接:Getting Started with the G1 Garbage Collector 概述 目的 这篇教程包含了G1垃圾收集器使用和它如何与HotSpot JVM配合使用的基本知识.你 ...
- Erlang Garbage Collector
Erlang Garbage Collector | Erlang Solution blog https://www.erlang-solutions.com/blog/erlang-garbage ...
- 提交并发量的方法:Java GC tuning :Garbage collector
三色算法,高效率垃圾回收,jvm调优 Garbage collector:垃圾回收器 What garbage? 没有任何引用指向它的对象 JVM GC回收算法: 引用计数法(ReferenceCou ...
- The Go Blog Getting to Go: The Journey of Go's Garbage Collector
Getting to Go: The Journey of Go's Garbage Collector https://blog.golang.org/ismmkeynote
随机推荐
- 【树链剖分/线段树】BZOJ1036-[ZJOI2008]树的统计Count
[题目大意] 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成 一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX ...
- [NEERC2007][SHOI2008]Cactus Reloaded
题目大意: 给你一个仙人掌,求图中相距最远的点对之间的距离. 思路: Tarjan+DP. 我们先考虑一个树的情况. 设用far[u]表示点u出发到其子树中叶子节点的最大距离,若v为u的子结点,很显然 ...
- 使用Spring Boot上传文件
原文:http://www.cnblogs.com/ityouknow/p/8298344.html 上传文件是互联网中常常应用的场景之一,最典型的情况就是上传头像等,今天就带着带着大家做一个Spri ...
- 使用Spring Boot集成FastDFS
原文:http://www.cnblogs.com/ityouknow/p/8298358.html#3893468 上篇文章介绍了如何使用Spring Boot上传文件,这篇文章我们介绍如何使用Sp ...
- javascript模块化有什么意义?
以前,所有的javascript都写在一个文件里,方便只加载一个文件就可以了,但是代码越来越多,必须分成多个文件加载,类似: <script src="1.js">&l ...
- vs 代理登入
https://msdn.microsoft.com/zh-cn/vstudio/dn771556.aspx
- javascript常见的数组方法
1:Array对象用于在单个变量中存储多个值typeof(arrArr) 'object'var arr1 = [];//创建一个空数组eg:数组是个引用类型var a = [1,2,3];var b ...
- 后台SQL注入实例
简要描述: 汉庭连锁酒店后台SQL注入,可绕过登陆限制进入后台,可脱库. 详细说明: 问题发生在这个站点.http://miaosha.htinns.com/ 标题内没有写具体信息.因为怕发布后被人入 ...
- HDU 3917 Road constructions(最小割---最大权闭合)
题目地址:HDU 3917 这题简直神题意... 题目本身就非常难看懂不说..即使看懂了.也对这题意的逻辑感到无语...无论了.. 就依照那题意上说的做吧... 题意:给你n个城市,m个公司.若干条可 ...
- jquery 事件,注册 与重复事件处理
jquery有时候会出现重复注册一个事件的问题,导致点击一个事件,这个事件被重复执行,也就是触发事件的次数有几次, 那么这个事件就会被执行叠加重复几次. 我这边做的一个项目,在某个页面初始化的时候,给 ...