首页 > 代码库 > C++中的简单内存管理---初步认识

C++中的简单内存管理---初步认识

OC里面给变量赋值有2种方法第一种是直接用下划线的,也就是实例变量:_button=       第二种是使用属性:self.button = ....这两种有何区别???

以下项目是创建了一个C++项目   简单模拟创建对象和给变量赋值的情况

首先创建了一个NSObject类,在OC里面继承NSObject类的都有retain  release  autorelease。。。。等方法来管理内存的


NSObject的头文件,声明方法

//
//  NSObject.h
//  autorelease
//
//  Created by 06 on 15/1/24.
//  Copyright (c) 2015年 黄永锐. All rights reserved.
//

#ifndef __autorelease__NSObject__
#define __autorelease__NSObject__

#include <iostream>

class NSObject{
    int m_retainCount;//计数器
    //这里面应该还有一个自动释放池的对象
    
public:
    //加1
    void retain();
    //减1
    void release();
    //自动释放
    void autorelease();
    
    //计数器的getter方法
    int retainCount();
};


#endif /* defined(__autorelease__NSObject__) */


NSObject的实现文件.cpp  里面实现了头文件里面声明的方法


//
//  NSObject.cpp
//  autorelease
//
//  Created by 06 on 15/1/24.
//  Copyright (c) 2015年 黄永锐. All rights reserved.
//

#include "NSObject.h"
using namespace std;

//加1
void NSObject:: retain(){
    m_retainCount++;
}
//减1
void NSObject:: release(){
    //如果当前对象不为空  并且引用计数器大于0
    if (this !=nullptr && m_retainCount > 0) {
        m_retainCount--;
    }
    
}
//自动释放
void NSObject:: autorelease(){
    //把当前对象添加到自动释放池当中  延迟release
    //当自动释放池对象释放的时候,会把里面保存的对象全部release一次
    //这里只是简单模拟,没有延迟释放
    m_retainCount--;
}

//计数器的getter方法
int NSObject:: retainCount(){
    return m_retainCount;
}


接着创建UIButton类继承于NSObject类

头文件

//
//  UIButton.h
//  autorelease
//
//  Created by 06 on 15/1/24.
//  Copyright (c) 2015年 黄永锐. All rights reserved.
//

#ifndef __autorelease__UIButton__
#define __autorelease__UIButton__

#include <iostream>
#include "NSObject.h"

class UIButton:public NSObject{
public:
    //创建对象
    static UIButton* button();
    //初始化方法
    void init();
    
};

#endif /* defined(__autorelease__UIButton__) */

UIButton类的实现文件.cpp

//
//  UIButton.cpp
//  autorelease
//
//  Created by 06 on 15/1/24.
//  Copyright (c) 2015年 黄永锐. All rights reserved.
//

#include "UIButton.h"
using namespace std;

//创建对象
UIButton* UIButton:: button(){
    //开辟内存空间
    UIButton* btn = new UIButton;//OC的这一步是alloc会导致引用计数器加1,而C++这一步没办法加1
    btn->retain();
    btn->init();
    
    //实际上这三步就相当于OC里面的[[..alloc]init]
    //现在是btn指针加1  注意 内存管理  谁加谁减。如果在这里直接release那么返回的可能就没有了,如果不release的话,btn这个指针在栈里出了这个方法就会弹栈了  就找不到btn了.....所以把它放在自动释放池里面,这样出了这个方法还能用,也不用考虑内存管理的问题
    
    btn->autorelease();
    
    return btn;
}
//初始化方法
void  UIButton:: init(){
    
}


//OC里面给变量赋值有2种方法 第一:_button   第二:self.button
// 创建对象  这里UIButton* button相当于_button = ...
//  UIButton* button = UIButton::button();//现在button引用计数器为1  因为autorelease还没有执行  如果不考虑延迟释放的问题,其实质上为0了。因为UIButton::button()里面加1 也减1了
//也就是说button的计数器为0  在这个方法里面可以用,出了这个方法就访问不到button了


最后创建一个MyClass类  也是继承NSObject

头文件

//
//  MyClass.h
//  autorelease
//
//  Created by 06 on 15/1/24.
//  Copyright (c) 2015年 黄永锐. All rights reserved.
//

#ifndef __autorelease__MyClass__
#define __autorelease__MyClass__

#include <iostream>
#include "UIButton.h"

//在OC里面声明一个属性,编译器会帮你做几件事呢??会生成一个保护的(实例)变量,还会生成2个公开的方法setter  getter

class MyClass : public NSObject{
public://公有的
    void setButton(UIButton* button);
    UIButton* getButton();
    
    //
    void setButton2(UIButton* button);
    UIButton* getButton2();
    
    //初始化方法
    void init();//初始化方法里把保护的_button指针创建出来让它指向一个对象
protected://保护的
    UIButton* _button;
    UIButton* _button2;
    
private://私有的
};

#endif /* defined(__autorelease__MyClass__) */

MyClass类的实现文件.cpp

//
//  MyClass.cpp
//  autorelease
//
//  Created by 06 on 15/1/24.
//  Copyright (c) 2015年 黄永锐. All rights reserved.
//

#include "MyClass.h"
using namespace std;

void MyClass:: init(){
    //在OC里面可以直接使用下划线创建对象
    _button = UIButton::button();//这种创建的对象出来引用计数器为0
    cout << "使用下划线创建对象的计数器为: " << _button->retainCount() << endl;
    
    
    //在OC里面还可以这样  self.相当于调用了button的setter方法
    //self.button = UIButton::button();//这样的计数器为1
    //在C++里面应该怎样呢?
    this->setButton(UIButton::button());
    cout << "使用setter方法创建对象的计数器为: " << _button->retainCount() << endl;
    
    
    this->setButton2(UIButton::button());//相当于self.button2 = ....//现在button2的引用计数器应该也为1
    cout << "button2 count: " << _button2->retainCount() << endl;
    
    
    
    UIButton *but = _button;//指向_button
    cout << "=== 赋值之前button1 button2的引用计数器都为1 ===" << endl;
    //调用button1的方法
    this->setButton(_button2); //相当于self.button = _button2;
#pragma 注意执行完这句之后_button也是指向了_button2对象了
    
    cout << "button1 count: " << _button->retainCount() << endl;//实际上是调用button2的retainCount
    cout << "button2 count: " << _button2->retainCount() << endl;
    cout << "_button原来指向的那个对象的引用计数器为: " << but->retainCount() << endl;  //出了方法就会被销毁
    
#pragma _button2要怎么释放?  现在_button 和_button2  都在用它
    //谁不用 谁减
    _button->release();
    cout << _button->retainCount() << endl;
    
    _button2->release();
    cout << _button2->retainCount() << endl;//到这里_button2的引用计数器为0了出了方法就会被销毁
}


#pragma mark - button 的setter getter方法
void MyClass:: setButton(UIButton* button){
    //1.判断是否自己负值
    if (_button == button) {
        return;//如果是自己给自己赋值  那就不用操作
    }else{
    //如果不是
        //2.先释放原有内存空间   在OC里面对已经是0的计数器再release也没关系
        _button->release();  //A-1
        
        //3.赋值操作
        _button = button;    //A = B
        //4.retain
        _button->retain();   //B++
    }
}


UIButton* MyClass:: getButton(){
    return _button;
}



#pragma mark - button2的setter getter方法

void MyClass:: setButton2(UIButton* button){
    if (_button2 == button) {
        return;
    }else{
        //2.先释放原有内存空间   在OC里面对已经是0的计数器再release也没关系
        _button2->release();
        //3.赋值操作
        _button2 = button;
        //4.retain
        _button2->retain();
    }
}

UIButton* MyClass:: getButton2(){
    return _button2;
}


在主函数里面创建MyClass对象


//
//  main.cpp
//  autorelease
//
//  Created by 06 on 15/1/24.
//  Copyright (c) 2015年 黄永锐. All rights reserved.
//

#include <iostream>
#include "MyClass.h"
using namespace std;



int main(int argc, const char * argv[])
{
    MyClass* myclass = new MyClass;
    myclass->init();
    
    //从输出结果可以看出,使用下划线创建对象的引用计数器为0.  使用setter方法创建的对象引用计数器为1
    return 0;
}


运行结果如下:

使用下划线创建对象的计数器为: 0
使用setter方法创建对象的计数器为: 1
button2 count: 1
=== 赋值之前button1 button2的引用计数器都为1 ===
button1 count: 2
button2 count: 2
_button原来指向的那个对象的引用计数器为: 0
1
0
Program ended with exit code: 0



/////////////////////////////// ======= 额外 ========  ////////////////////////////////////

数组里面也会给元素 1

 数组里面为什么只能放对象??就是因为加 1

 数组addObject一个元素进数组的时候,数组会负责给传进来的元素加1

 为什么数组要加1??谁用谁加。把元素放进数组里,也就是数组要用。

 怎么加?

 会调用你传进来的那个元素的retain方法,但是你的这个对象没有继承NSObject,不存在retain方法,就会出现问题了。例如传进一个int 100;  100根本就没有retain方法。 所以要把int封装成NSNumber类型,因为NSNumber继承NSObject

 

 数组addObject的时候会加那么什么时候会减1??

 它用它加,不用了remove的时候会减1.

 

 另外一种情况:不断的往数组里面添加元素,现在数组要销毁了,在销毁之前并没有全部remove

 会不会有内存泄漏??

 也不会,因为数组先把它里面所有的元素都release一次,自己才销毁.




C++中的简单内存管理---初步认识