2019独角兽企业重金招聘Python工程师标准>>>

2dx引擎中的对象内存管理模型,很简单就是一个对象池+引用计数,本着学好2dx的好奇心,先这里开走吧,紧接上面两节,首先我们看一个编码场景代码:

hello word :

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__#include "cocos2d.h"class HelloWorld : public cocos2d::CCLayer
{
public:// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphonevirtual bool init();  // there's no 'id' in cpp, so we recommend returning the class instance pointerstatic cocos2d::CCScene* scene();// a selector callbackvoid menuCloseCallback(CCObject* pSender);// implement the "static node()" method manuallyCREATE_FUNC(HelloWorld);
};#endif // __HELLOWORLD_SCENE_H__
#include "HelloWorldScene.h"USING_NS_CC;CCScene* HelloWorld::scene()
{// 'scene' is an autorelease objectCCScene *scene = CCScene::create();// 'layer' is an autorelease objectHelloWorld *layer = HelloWorld::create();// add layer as a child to scenescene->addChild(layer);// return the scenereturn scene;
}// on "init" you need to initialize your instance
bool HelloWorld::init()
{//// 1. super init firstif ( !CCLayer::init() ){return false;}CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();/// 2. add a menu item with "X" image, which is clicked to quit the program//    you may modify it.// add a "close" icon to exit the progress. it's an autorelease objectCCMenuItemImage *pCloseItem = CCMenuItemImage::create("CloseNormal.png","CloseSelected.png",this,menu_selector(HelloWorld::menuCloseCallback));pCloseItem->setPosition(ccp(origin.x + visibleSize.width - pCloseItem->getContentSize().width/2 ,origin.y + pCloseItem->getContentSize().height/2));// create menu, it's an autorelease objectCCMenu* pMenu = CCMenu::create(pCloseItem, NULL);pMenu->setPosition(CCPointZero);this->addChild(pMenu, 1);/// 3. add your codes below...// add a label shows "Hello World"// create and initialize a labelCCLabelTTF* pLabel = CCLabelTTF::create("Hello World", "Arial", 24);// position the label on the center of the screenpLabel->setPosition(ccp(origin.x + visibleSize.width/2,origin.y + visibleSize.height - pLabel->getContentSize().height));// add the label as a child to this layerthis->addChild(pLabel, 1);// add "HelloWorld" splash screen"CCSprite* pSprite = CCSprite::create("HelloWorld.png");// position the sprite on the center of the screenpSprite->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));// add the sprite as a child to this layerthis->addChild(pSprite, 0);return true;
}//close application
void HelloWorld::menuCloseCallback(CCObject* pSender)
{CCDirector::sharedDirector()->end();#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)exit(0);
#endif
}

代码片段中有一个 CREATE_FUNC(HelloWorld);   HelloWorld *layer = HelloWorld::create();

跟进看到,其实创建这个层的方法就是定义的CREATE_FUNC(xx);继续追踪,可以看到,他创建这个层,同时会调用初始化inti()方法--准备layer基础数据,也就是java上见的多的多态,这不是重点,他调用了,autorelease(),也就是我们对象内存模型中的自动管理方法,这里我先直接总结下,对象在创建的过程中,创建之后,调用autorelease(),就会被添加到对象池中自动维护计数,当计数未0(在每一帧结束后),或者在析构中调用销毁,那么就将会冲对象池中移除;在看一个例子:CCArray *test=CCArray::create();test->retain();

这样才是才会创建成功(额排除其他异常);当我们创建这个对象的时候,create()在返回这个对象的同时会将对象自动autorelease();所以你必须还得引用计数+1;为什么?

因为autorelease()将对象添加到对象池中,会自动release(),引用计算--1;默认引用计数为1,当对象创建的时候,所以知道为什么会创建失败了吧 如果标记对象被引用;当然你自己创建的对象就要这样处理,如果是2dx的捏?那就直接穿件创建autorelease(),内存对象池会自动处理的;

接下来直接看内存模型+引用计数,内存对象缓存是用的CCArray;具体看下面代码片段,该有的注解都有了:

先是2dx中:object,java中所有对象的根接点,这里你可以这样“理解”:

/****************************************************************************
Copyright (c) 2010 cocos2d-x.orghttp://www.cocos2d-x.orgPermission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/#ifndef __CCOBJECT_H__
#define __CCOBJECT_H__#include "CCDataVisitor.h"#ifdef EMSCRIPTEN
#include <GLES2/gl2.h>
#endif // EMSCRIPTENNS_CC_BEGIN/*** @addtogroup base_nodes* @{*/class CCZone;
class CCObject;
class CCNode;
class CCEvent;class CC_DLL CCCopying
{
public:virtual CCObject* copyWithZone(CCZone* pZone);
};
//对象继承CCobject 都可以引用自动释放池对象(引用计数+释放池管理类)
//根据开发的内容来划分池对象,譬如一个场景创建一个自动释放池,游戏中场景切换时,释放缓冲区最好时间
//引擎基类
class CC_DLL CCObject : public CCCopying
{
public:// 对象IDunsigned int        m_uID;// Lua reference idint                 m_nLuaID;
protected:// 计数对象unsigned int        m_uReference;// count of autorelease 计数自动释放对象unsigned int        m_uAutoReleaseCount;
public:CCObject(void);virtual ~CCObject(void);void release(void);void retain(void);CCObject* autorelease(void);CCObject* copy(void);bool isSingleReference(void) const;unsigned int retainCount(void) const;virtual bool isEqual(const CCObject* pObject);virtual void acceptVisitor(CCDataVisitor &visitor);virtual void update(float dt) {CC_UNUSED_PARAM(dt);};//自动释放池friend class CCAutoreleasePool;
};typedef void (CCObject::*SEL_SCHEDULE)(float);
typedef void (CCObject::*SEL_CallFunc)();
typedef void (CCObject::*SEL_CallFuncN)(CCNode*);
typedef void (CCObject::*SEL_CallFuncND)(CCNode*, void*);
typedef void (CCObject::*SEL_CallFuncO)(CCObject*);
typedef void (CCObject::*SEL_MenuHandler)(CCObject*);
//if button ,do CCEvent *evnet  参数
typedef void (CCObject::*SEL_EventHandler)(CCEvent*);
typedef int (CCObject::*SEL_Compare)(CCObject*);
//各种回调函数接口!!!
#define schedule_selector(_SELECTOR) (SEL_SCHEDULE)(&_SELECTOR)
#define callfunc_selector(_SELECTOR) (SEL_CallFunc)(&_SELECTOR)
#define callfuncN_selector(_SELECTOR) (SEL_CallFuncN)(&_SELECTOR)
#define callfuncND_selector(_SELECTOR) (SEL_CallFuncND)(&_SELECTOR)
#define callfuncO_selector(_SELECTOR) (SEL_CallFuncO)(&_SELECTOR)
#define menu_selector(_SELECTOR) (SEL_MenuHandler)(&_SELECTOR)
#define event_selector(_SELECTOR) (SEL_EventHandler)(&_SELECTOR)
#define compare_selector(_SELECTOR) (SEL_Compare)(&_SELECTOR)// end of base_nodes group
/// @}NS_CC_END#endif // __CCOBJECT_H__
/****************************************************************************
Copyright (c) 2010 cocos2d-x.orghttp://www.cocos2d-x.orgPermission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/#include "CCObject.h"
#include "CCAutoreleasePool.h"
#include "ccMacros.h"
#include "script_support/CCScriptSupport.h"NS_CC_BEGINCCObject* CCCopying::copyWithZone(CCZone *pZone)
{CC_UNUSED_PARAM(pZone);CCAssert(0, "not implement");return 0;
}/************************************************************************/
/* 构造函数                                                                     */
/************************************************************************/
CCObject::CCObject(void)
: m_nLuaID(0)
, m_uReference(1) // when the object is created, the reference count of it is 1
, m_uAutoReleaseCount(0)
{static unsigned int uObjectCount = 0;m_uID = ++uObjectCount;
}CCObject::~CCObject(void)
{// if the object is managed, we should remove it// from pool managerif (m_uAutoReleaseCount > 0){CCPoolManager::sharedPoolManager()->removeObject(this);}// if the object is referenced by Lua engine, remove itif (m_nLuaID){CCScriptEngineManager::sharedManager()->getScriptEngine()->removeScriptObjectByCCObject(this);}else{CCScriptEngineProtocol* pEngine = CCScriptEngineManager::sharedManager()->getScriptEngine();if (pEngine != NULL && pEngine->getScriptType() == kScriptTypeJavascript){pEngine->removeScriptObjectByCCObject(this);}}
}CCObject* CCObject::copy()
{return copyWithZone(0);
}//当引用计数为0时,释放对象 delete
void CCObject::release(void)
{CCAssert(m_uReference > 0, "reference count should greater than 0");--m_uReference;if (m_uReference == 0){delete this;}
}/************************************************************************/
/* 引用计数         +1 标记对象被引用                                                           */
/************************************************************************/
void CCObject::retain(void)
{CCAssert(m_uReference > 0, "reference count should greater than 0");++m_uReference;
}//将对象添加到释放池中
CCObject* CCObject::autorelease(void)
{CCPoolManager::sharedPoolManager()->addObject(this);return this;
}//判断是否单引用
bool CCObject::isSingleReference(void) const
{return m_uReference == 1;
}unsigned int CCObject::retainCount(void) const
{return m_uReference;
}bool CCObject::isEqual(const CCObject *pObject)
{return this == pObject;
}void CCObject::acceptVisitor(CCDataVisitor &visitor)
{visitor.visitObject(this);
}NS_CC_END

注意当你autoRelease()的时候,就将对象添加到内存CCAutoreleasePool对象中,同时release(),引用计数--1;如果0,不好意思 就干掉;所以创建有些对象要记得引用计数+1,析构中销毁就对了,剩下的交给2dx内存对象模型处理;具体过程看下面代码片段:

/****************************************************************************
Copyright (c) 2010 cocos2d-x.orghttp://www.cocos2d-x.orgPermission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#ifndef __AUTORELEASEPOOL_H__
#define __AUTORELEASEPOOL_H__#include "CCObject.h"
#include "CCArray.h"NS_CC_BEGIN/*** @addtogroup base_nodes* @{*/class CC_DLL CCAutoreleasePool : public CCObject
{CCArray*    m_pManagedObjectArray;
public:CCAutoreleasePool(void);~CCAutoreleasePool(void);void addObject(CCObject *pObject);void removeObject(CCObject *pObject);void clear();
};
//自动释放池
class CC_DLL CCPoolManager
{CCArray*    m_pReleasePoolStack;    CCAutoreleasePool*                    m_pCurReleasePool;CCAutoreleasePool* getCurReleasePool();
public:CCPoolManager();~CCPoolManager();void finalize();void push();void pop();void removeObject(CCObject* pObject);void addObject(CCObject* pObject);static CCPoolManager* sharedPoolManager();static void purgePoolManager();friend class CCAutoreleasePool;
};// end of base_nodes group
/// @}NS_CC_END#endif //__AUTORELEASEPOOL_H__/****************************************************************************
Copyright (c) 2010 cocos2d-x.orghttp://www.cocos2d-x.orgPermission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "CCAutoreleasePool.h"
#include "ccMacros.h"NS_CC_BEGINstatic CCPoolManager* s_pPoolManager = NULL;//new 一个 array容器。缓存object对象
CCAutoreleasePool::CCAutoreleasePool(void)
{m_pManagedObjectArray = new CCArray();m_pManagedObjectArray->init();
}CCAutoreleasePool::~CCAutoreleasePool(void)
{CC_SAFE_DELETE(m_pManagedObjectArray);
}/************************************************************************/
/*                                                                      */
/************************************************************************/
void CCAutoreleasePool::addObject(CCObject* pObject)
{m_pManagedObjectArray->addObject(pObject);CCAssert(pObject->m_uReference > 1, "reference count should be greater than 1");++(pObject->m_uAutoReleaseCount);//释放对象 ,如果new 一个 ,那么要标记对象+1 ,回调函数retain(),否则会创建对象失败pObject->release(); // no ref count, in this case autorelease pool added.
}
//就是一个从数组中移除对象,java知道吧  List一样的
void CCAutoreleasePool::removeObject(CCObject* pObject)
{for (unsigned int i = 0; i < pObject->m_uAutoReleaseCount; ++i){m_pManagedObjectArray->removeObject(pObject, false);}
}
//释放池中所有对象,在每一帧后,message loop,将会删除autoRelease的对象
void CCAutoreleasePool::clear()
{if(m_pManagedObjectArray->count() > 0){//CCAutoreleasePool* pReleasePool;
#ifdef _DEBUGint nIndex = m_pManagedObjectArray->count() - 1;
#endifCCObject* pObj = NULL;CCARRAY_FOREACH_REVERSE(m_pManagedObjectArray, pObj){if(!pObj)break;--(pObj->m_uAutoReleaseCount);//(*it)->release();//delete (*it);
#ifdef _DEBUGnIndex--;
#endif}m_pManagedObjectArray->removeAllObjects();}
}//--------------------------------------------------------------------
//
// CCPoolManager
//
//--------------------------------------------------------------------CCPoolManager* CCPoolManager::sharedPoolManager()
{if (s_pPoolManager == NULL){s_pPoolManager = new CCPoolManager();}return s_pPoolManager;
}void CCPoolManager::purgePoolManager()
{CC_SAFE_DELETE(s_pPoolManager);
}CCPoolManager::CCPoolManager()
{m_pReleasePoolStack = new CCArray();    m_pReleasePoolStack->init();m_pCurReleasePool = 0;
}CCPoolManager::~CCPoolManager()
{finalize();// we only release the last autorelease pool here m_pCurReleasePool = 0;m_pReleasePoolStack->removeObjectAtIndex(0);CC_SAFE_DELETE(m_pReleasePoolStack);
}void CCPoolManager::finalize()
{if(m_pReleasePoolStack->count() > 0){//CCAutoreleasePool* pReleasePool;CCObject* pObj = NULL;CCARRAY_FOREACH(m_pReleasePoolStack, pObj){if(!pObj)break;CCAutoreleasePool* pPool = (CCAutoreleasePool*)pObj;pPool->clear();}}
}void CCPoolManager::push()
{CCAutoreleasePool* pPool = new CCAutoreleasePool();       //ref = 1m_pCurReleasePool = pPool;m_pReleasePoolStack->addObject(pPool);                   //ref = 2pPool->release();                                       //ref = 1
}void CCPoolManager::pop()
{if (! m_pCurReleasePool){return;}int nCount = m_pReleasePoolStack->count();m_pCurReleasePool->clear();if(nCount > 1){m_pReleasePoolStack->removeObjectAtIndex(nCount-1);//         if(nCount > 1)
//         {
//             m_pCurReleasePool = m_pReleasePoolStack->objectAtIndex(nCount - 2);
//             return;
//         }m_pCurReleasePool = (CCAutoreleasePool*)m_pReleasePoolStack->objectAtIndex(nCount - 2);}/*m_pCurReleasePool = NULL;*/
}void CCPoolManager::removeObject(CCObject* pObject)
{CCAssert(m_pCurReleasePool, "current auto release pool should not be null");m_pCurReleasePool->removeObject(pObject);
}void CCPoolManager::addObject(CCObject* pObject)
{getCurReleasePool()->addObject(pObject);
}CCAutoreleasePool* CCPoolManager::getCurReleasePool()
{if(!m_pCurReleasePool){push();}CCAssert(m_pCurReleasePool, "current auto release pool should not be null");return m_pCurReleasePool;
}NS_CC_END


下面一段摘自:http://blog.csdn.net/ring0hx/article/details/7946397

手动内存管理似乎比new/delete更麻烦,而且并没有解决一开始我们提到的函数内创建的对象的生命周期超出函数怎么办的问题。new和release需配对使用,那在函数内创建的对象返回前我们需要调用一次release,在这之前如果我们没有把对象加入到什么集合中,对象就被销毁了,和使用new/delete是一样的。自动内存管理就可以解决这个问题。CCObject有一个autorelease方法,如果一个对象在用new关键字创建之后调用了autorelease,我们就不必关心它的释放问题。CCPoolManager会在游戏的每一帧结束后自动释放这些autorelease的对象。CCPoolManager其实依然是通过引用计数来管理对象生命周期的,它里面有一个CCAutoreleasePool,我们调用CCObject的autorelease就是把自己加入到CCAutoreleasePool的对象数组里面。当每一帧结束的时候,CCPoolManager会将对象从数组中移除,如果这时候对象的引用计数为0,对象就自然被释放了。 对于用new关键字创建之后调用了autorelease的对象,不需要再release一次。
cocos2dx中的大部分对象都可以通过静态工厂方法来创建出这种会自动释放的对象,这是cocos2dx的一条规则,我们自己实现的类最好也遵循这样的规则,以免引起其他开发人员误会。如果一个对象是通过类的静态方法创建而不是new出来的,我们就不需要release它。

其实这里的自动并没有我们想得那么好,对于像C#,Java这种托管语言,虚拟机为你完成了所有内存管理工作,程序员完全从内存分配和释放中解脱了出来。cocos2dx的autorelease只不过每帧结束后自动在为我们释放了一次对象, 如果我们希望创建的对象在下一帧仍然可以使用,我们需要显式地retain一下这个对象或者把对象加入到集合中(集合会帮我们retain一次)。既然retain了,我们还是不能忘记在适当的地方release。比较常见的用法是创建一个autorelease对象作为类成员变量,我们在通过静态方法得到实例的指针后除了赋值给类成员,还要retain一次,然后在类的析构函数中release一次。如果没有retain,以后使用该成员的时候就会因为对象被销毁而发生内存访问错误,这是新手很容易遇到的陷阱。

想了解更多 你也可以看这里,个人觉得这里翻译,以及写的都不错:http://my.oschina.net/wangxuanyihaha/blog/131735

综上所述,2dc引擎中创建了对象 记得添加到对象池中,以便在合适的时机2dx引擎帮你回收内存,其实这个也不是大问题 洁身自好就没事的( 上了厕所要搽干净pp) 你觉得呢?ps:本系列文章会持续更新,后期就会直接根据各个模块单独demo上起,最后出个游戏demo,有问题的请留言,互相学习

转载于:https://my.oschina.net/chenleijava/blog/183167

跟着石头哥哥学cocos2d-x(三)---2dx引擎中的内存管理模型相关推荐

  1. 跟着石头哥哥学cocos2d-x(四)--cocos2dx中的动画以及TexturePacker使用

    2019独角兽企业重金招聘Python工程师标准>>> 之前向Andreas Loew申请了一枚TexturePacker注册码,很快都下来了,作为回报我打算还是写一篇关于Textu ...

  2. IA-32系统编程指南 - 第三章 保护模式的内存管理【1】

    第三章 保护模式的内存管理[1] [作者:lion3875 原创文章 参考文献<Intel 64 and IA-32 system programming guide>] IA-32保护模 ...

  3. IA-32系统编程指南 - 第三章 保护模式的内存管理【2】

    第三章 保护模式的内存管理[2]     [作者:lion3875 原创文章 参考文献<Intel 64 and IA-32 system programming guide>]     ...

  4. 跟着鸟哥学linux【三】

    我们来试试超级简单的nano 神奇vim一直还没学到 首先输入nano xxx.text 如果有xxx就打开没有就新建 然后下面的框都写得很清楚 只需要ctrl+ 就行了 就是一个简单的记事本 syn ...

  5. 【Java】跟着小丛学Java第三阶段:Java核心API

    异常处理 什么是异常 在编写Java应用程序时,可能会遇到各种类型的错误,例如输入无效的数据或尝试访问不存在的文件等.当这种错误发生时,Java会抛出一个异常,这可能会导致程序崩溃或产生不可预测的结果 ...

  6. Flask最强攻略 - 跟DragonFire学Flask - 第三篇 Flask 中的 request 之 先知道有这么个东西...

    每个框架中都有处理请求的机制(request),但是每个框架的处理方式和机制是不同的 为了了解Flask的request中都有什么东西,首先我们要写一个前后端的交互 基于HTML + Flask 写一 ...

  7. LevelDB 源码剖析(三)公共基础:内存管理、数值编码、Env家族、文件操作

    文章目录 内存管理 Arena 结构 内存分配 内存使用率统计 TCMalloc Env家族 PosixEnv EnvWrapper InMemoryEnv 文件操作 SequentialFile W ...

  8. ios 内存管理的理解(三)ARC下 对象内存管理

    1 ARC工作原理详述 ARC是Objective-C编译器的特性,而不是运行时特性或者垃圾回收机制,ARC所做的只不过是在代码编译时为你自动在合适的位置插入release或autorelease 2 ...

  9. 三分钟快速理解javascript内存管理

    javascript中具有垃圾自动回收机制(Garbage Collection),也就是执行环境会负责管理代码执行过程中使用的内存,在开发过程中就可以不考虑内存的分配,以及无用内存释放的问题.但是触 ...

最新文章

  1. mysql drop_mysql恢复drop掉的表
  2. 青岛计算机类职业中学,青岛最好的职业学校有哪些?
  3. VS2013中CUDA的配置
  4. Linux系统CPU相关信息查询
  5. CCF NOI1069 分解因数
  6. 小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_5-3.微信Oauth2.0交互流程讲解...
  7. Win10系统蓝屏错误DPC怎么解决【系统天地】
  8. echarts地图数据与世界地图中英文转换
  9. Altium designer—STM32F103ZET6最小系统原理图
  10. 图解yarn的作业提交流程
  11. ftp上传工具,八款最佳的ftp上传下载工具,支持中文(ftp客户端分享)
  12. 移动硬盘损坏怎么恢复?看完再也不怕丢失数据
  13. 分布式光伏运维服务器,户用分布式光伏电站运维指导手册——运维及安全
  14. xmanager 5 破解版,有需要自己下载
  15. C4D基础学习(二)-移动与捕捉工具
  16. IIS管理器使用-修改根节点名称
  17. ESD防静电监控系统后台实时掌控现场静电防护情况
  18. ICASSP2023|达摩院语音实验室入选论文全况速览
  19. SSL peer certificate or SSH remote key was not OK
  20. 中国风电法兰行业研究与投资前景预测报告(2021版)

热门文章

  1. 如何将广告始终定位到网页右下角
  2. Swift - 使用addSubview()方法将StoryBoard中的视图加载进来
  3. iOSSharing #9 | 2019-05-19
  4. 手机APP自动化之uiautomator2 +python3 UI自动化
  5. autohotkey快捷键
  6. Spring MVC-ContextLoaderListener和DispatcherServlet
  7. 随机存取:fseek(),ftell()
  8. Express结合Webpack的全栈自动刷新
  9. MyEclipse插件安装
  10. 关于SQLServer2005的学习笔记——约束、Check、触发器的执行顺序