标签: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
// 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
// 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 , 那么什么时候会减1??
它用它加,不用了remove的时候会减1.
另外一种情况:不断的往数组里面添加元素,现在数组要销毁了,在销毁之前并没有全部remove
会不会有内存泄漏??
也不会,因为数组先把它里面所有的元素都release一次,自己才销毁.
标签:c++内存管理
原文地址:http://blog.csdn.net/love9099/article/details/43084979