#ifndef _SINGLETON_H_
#define _SINGLETON_H_
class Singleton
{
private:
//定义一个私有的静态全局变量来保存该类的唯一实例
static Singleton* pInstance;//静态成员,保存对象的唯一实例
/// 构造函数必须是私有的
/// 这样在外部便无法使用 new 来创建该类的实例
Singleton();//私有化构造函数,使其无法在类外实例化
public:
/// 定义一个全局访问点
/// 设置为静态方法
/// 则在类的外部便无需实例化就可以调用该方法
static Singleton* Instance();
//void Destroy();
static void Destroy();
};
#endif
===============================================================================================================
===============================================================================================================
#include "Singleton.h"
#include <iostream>
using namespace std;
Singleton* Singleton::pInstance = NULL;
Singleton::Singleton()
{
cout<< "Singleton..." << endl;
}
//尽管我两次访问了 GetInstance(),但是我访问的只是同一个实例,
Singleton* Singleton::Instance()
{
//这里可以保证只实例化一次
//即在第一次调用时实例化
//以后调用便不会再实例化
if(NULL == pInstance)
{
pInstance = new Singleton();
}
return pInstance;
}
void Singleton::Destroy()
{
delete pInstance;
pInstance = NULL;
cout<< "Destroy..." << endl;
}
==============================================================================================
=============================================================================================
#include "Singleton.h"
#include <iostream>
using namespace std;
int main()
{
Singleton* ps = Singleton::Instance();//通过全局访问点获取实例
Singleton::Destroy();
return 0;
}
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
class Singleton
{
public:
static Singleton* getInstance( );
~Singleton( );
private:
Singleton( );
static Singleton* instance;
};
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
const和类
(1)const修饰成员变量
const修饰类的成员函数,表示成员常量,不能被修改,同时它只能在初始化列表中赋值。
class A
{
…
const int nValue; //成员常量不能被修改
…
A(int x): nValue(x) { } ; //只能在初始化列表中赋值
}
(2)const修饰成员函数
const修饰类的成员函数,则该成员函数不能修改类中任何非const成员函数。一般写在函数的最后来修饰。
class A
{
…
void function()const; //常成员函数, 它不改变对象的成员变量.
//也不能调用类中任何非const成员函数。
}
对于const类对象/指针/引用,只能调用类的const成员函数,因此,const修饰成员函数的最重要作用就是限制对于const对象的使用。
a. const成员函数不被允许修改它所在对象的任何一个数据成员。
b. const成员函数能够访问对象的const成员,而其他成员函数不可以。
(3)const修饰类对象/对象指针/对象引用
· const修饰类对象表示该对象为常量对象,其中的任何成员都不能被修改。对于对象指针和对象引用也是一样。
· const修饰的对象,该对象的任何非const成员函数都不能被调用,因为任何非const成员函数会有修改成员变量的企图。
例如:
class AAA
{
void func1();
void func2() const;
}
const AAA aObj;
aObj.func1(); ×
aObj.func2(); 正确
const AAA* aObj = new AAA();
aObj-> func1(); ×
aObj-> func2(); 正确
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
举了一些
C/C++
中用到
const
的地方。
1
,
const
变量
2
,
const
指针
3
,
const
引用
4
,
const
类
5
,类的
const
成员变量
6
,类的
const
成员函数
7
,
const
修饰函数的形参与返回值
下面我们分别讨论上面几种情况下,
const
的用法。
举了一些
C/C++
中用到
const
的地方。
1
,
const
变量
2
,
const
指针
3
,
const
引用
4
,
const
类
5
,类的
const
成员变量
6
,类的
const
成员函数
7
,
const
修饰函数的形参与返回值
下面我们分别讨论上面几种情况下,
const
的用法。
举了一些C/C++中用到const的地方。
1,const变量
2,const指针
3,const引用
4,const类
5,类的const成员变量
6,类的const成员函数
7,const修饰函数的形参与返回值
、、、、、、、、、、、、、、、、、、、、、、、、、
const引用引用引用引用引用引用引用
-------------------------------------基础知识1
int a=10;
int &b=a;//声明b是a的引用,这样a的值变以后,b的值也变;b的值变以后,a的值也跟着变。
------------------------------------基础知识2
int ival=1024;
int *pi=&ival; //pi指向一个int型的数
int **ppi=&pi; //ppi指向一个int型的指针
---------------------基础知识3
类的const数据成员
在类内部,const数据成员代表在对象的生命周期内该数据成员不可更改,也就是说这个const修饰的是该对象的一个数据,它是属于对象的,只有在该对象的有效期内起作用
2、类的static数据成员
在类内部,static数据成员代表了属于整个类的数据,并不属于单个对象,因此它在整个程序的运行过程中只有一个副本,不能在定义对象时对static成员进行初始化,就是不能用构造函数进行初始化。
------------------基础知识4
重载操作符的三个准则
1.右端值要为const 类型(不想改变他的值)Take a const-reference for the argument (the right-hand side of the assignment).
2.要返回一个引用,以便于实现(a=b=c…… (Do this by returning *this.)
3.检查是否为自我赋值Check for self-assignment, by comparing the pointers (this to &rhs).
------------------基础知识5
C++中,若类的方法前加了static关键字,则该方法称为静态方法,反之为实例方法。静态方法为类所有,可以通过对象来使用,也可以通过类来使用。但一般提倡通过类名来使用,因为静态方法只要定义了类,不必建立类的实例就可使用。静态方法只能用类的静态成员。
、、、、、、、、、、、、、、、、、、、、、、、、、、
int ival = 1092;
int &re =ival;
int &re2 = &ival;//错误
int *pi=&ival;
int *&pi2 = pi;
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
double dval=3.134
//下3行仅对const引用才是合法的
const int &ir=1024
cons
t int &ir2=dval;
const double &dr=dval+1.0
、、、、、、、、、、、、、、、、、、、、、、、、、、
int iv=100;
int *&pir=&iv;//错误,非const引用对需要临时对象的引用
int *const &pir=&iv;
const int ival = 1024;
int *&pi_ref = &ival; //错误,非const引用是非法的
const int *&pi_ref = &ival; //错误,需要临时变量,且引用的是指针,而pi_ref是一个非常量指针
const int * const &pi_ref = &ival; //正确
//补充
const int *p = &ival;
const int *&pi_ref = p; //正确
、、、、、、、、、、、、、、、、、、、、、、、、、、、、
1.不允许非const引用指向需要临时对象的对象或值
int a = 2;
int &ref1 = a;// OK.有过渡变量。
const int &ref2 = 2;// OK.编译器产生临时变量,需要const引用
2.地址值是不可寻址的值
int * const &ref3 = &a; // OK;
3.于是,用const对象的地址来初始化一个指向指针的引用
const int b = 23;
const int *p = &b;
const int *& ref4 = p;
const int *const & ref5 = &b; //OK
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
下面我们分别讨论上面几种情况下,const的用法。
class S
{
public:
static S& getInstance()
{
static S instance; // Guaranteed to be destroyed.
// Instantiated on first use.
return instance;
}
private:
S() {} // Constructor? (the {} brackets) are needed here.
// C++ 03
// ========
// Dont forget to declare these two. You want to make sure they
// are unacceptable otherwise you may accidentally get copies of
// your singleton appearing.
//,拷贝构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它必须的一个参数是本类型的一个引用变量。
S(S const&); // Don't Implement
void operator=(S const&); // Don't implement//操作符重载
// C++ 11
// =======
// We can use the better technique of deleting the methods
// we don't want.
public:
S(S const&) = delete;
void operator=(S const&) = delete;
// Note: Scott Meyers mentions in his Effective Modern
// C++ book, that deleted functions should generally
// be public as it results in better error messages
// due to the compilers behavior to check accessibility
// before deleted status
};
111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
private static Drawable sBackground;
@Override
protectedvoid onCreate(Bundle state){
super.onCreate(state);
TextView label =newTextView(this);
label.setText("Leaks are bad");
if(sBackground ==null){
sBackground = getDrawable(R.drawable.large_bitmap);
}
label.setBackgroundDrawable(sBackground);
setContentView(label);
}
上面几行代码,内存泄露挺严重的。sBackground是一个 static 变量,在 label调用setBackgroundDrawable的时候,会调用sBackground的setCallback,所以在sBackground中就存在label的引用。
而,label中又存在Activity的引用,所以此Activity一直不会被回收,即使已经finish了。
如何避免:
- 使用applicationContext作为上下文,避免使用activity
- 设置Drawable的Callback为null
- 在Service或者Activity使用内部类尽量使用static类。例如:使用Handler
实用的Bean工厂ApplicationContext
ApplicationContext的中文意思是“应用前后关系”,它继承自BeanFactory接口,除了包含BeanFactory的所有功能之外,在国际化支持、资源访问(如URL和文件)、事件传播等方面进行了良好的支持,被推荐为Java EE应用之首选,可应用在Java APP与Java Web中。
关于第3点,看个例子:
1 static class IncomingHandlerextendsHandler {
2 private final WeakReference<UDPListenerActivity> mActivity;
3
4 IncomingHandler(UDPListenerActivity activity) {
5 mService = newWeakReference < UDPListenerActivity > (activity);
6 }
7
8 @Override
9 public void handleMessage(Message msg) {
10 UDPListenerActivity activity = mActivity.get();
11 if (activity != null) {
12 activity.handleMessage(msg);
13 }
14 }
15 }
我们知道,Message发出之后是存在MessageQueue中的,有些Message也不是马上就被处理的。在Message存在一个 target,是Handler的一个引用,如果Message在Queue中存在的时间越长,就会导致Handler无法被回收。如果Handler是非静态的,则会导致Activity或者Service不会被回收。
所以正确处理Handler等之类的内部类,应该采用上述代码。
222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
很多地方我们需要使用到Context,比如我们自定义一个单例的CustomManager,当我们使用一些系统的服务时,就需要Context参数,这时如果使用Activity或者Service 作为context,就会容易造成内存泄露。
具体原因请看下面的这个例子:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">pubic class CustomManager {
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> CustomManager sInstance;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> CustomManager <span class="hljs-title" style="box-sizing: border-box;">getInstance</span>(Context context) {
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (sInstance == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 这个类拥有了一个静态的context引用 </span>
sInstance = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> CustomManager(context);
}
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> sInstance;
}
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> Context mContext;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-title" style="box-sizing: border-box;">CustomManager</span>(Context context) {
mContext = context;
}
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li></ul>
当所持有的Context的引用是一个Activity或者Service,系统销毁它们后,由于CustomManager中有其静态的引用,所以Activity或者Service所占用的资源并不会被回收,造成内存泄露。
那么正确的方法是使用Application的context, 因为Application的context是单例的,并且它的生命周期属于整个应用进程。所以上边的代码需要改成:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> CustomManager sInstance;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> CustomManager <span class="hljs-title" style="box-sizing: border-box;">getInstance</span>(Context context) {
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (sInstance == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 这个类拥有了一个静态的context引用 </span>
sInstance = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> CustomManager(context.getApplicationContext());
}
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> sInstance;
}
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> Context mContext;
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul>