单例模式本身很简单,就是为一个类只创建一个对象。并在全局引用这个对象。单例模式包含了两层涵义:
- 一个类只有一个对象
- 这个对象会被全局访问
要实现一个简单的单例也很容易:
class A {
public:
static A *GetInstance() {
if (a != nullptr) {
a = new A;
}
return a;
}
private:
A *a;
};
这里我故意用了一个千疮百孔的单例实现。下面我就列出这个单例的问题。
简单单例的问题
谁来释放这个对象?
因为a是一个指针,指针变量是一个POD(plain of data)变量。所以没有人会帮你调用A的析构函数。这可能会造成内存泄漏。但进程退出时,所有该进程分配的内存和系统资源都会被标记成释放。但如果这里涉及到线程,情况会有些许不同。一个joinable线程,如果不在进程结束前join,就会发生资源泄漏,产生僵尸线程。但这不是本文想重点阐述的问题。因为释放这种单例内存的方法有很多,比如:
- 定义一个deletor类,再定义一个static的deletor对象,并在deletor对象中释放a
- 直接用局部静态变量
- 或者将
A *a
定义成智能指针
如何处理并发?
如果GetInstance函数被并发访问,上面的简单单例实现会有并发问题。即a可能被重复赋值,从而产生了几个野对象。解决这个问题比较优雅点的办法就是用std::call_once
,如下:
class A {
public:
static A& GetInstance() {
std::once_flag flag;
std::call_once(flag, []()(
if (a != nullptr) {
a = new A;
}
});
return *a;
}
private:
A *a;
};
这里返回值从指针,变成了引用。言下之意,单例的获取在程序整个生命周期内从来不会失败。不过这是理想状况,在某些模型下,我们不得不让单例返回空指针。
另外,C++11的语言规范定义了局部静态对象的构造析构行为,确保其只会被构造一次。所以在C++11及以上的场景下,最优雅的代码如下:
class A {
public:
A& GetInstance() {
static A a;
return a;
}
};
这就是著名的Meyer's Singleton,既简洁又不会犯错,可惜只能用于C++11以后的版本。
析构顺序?
可以引出今天的主角了。单例模式如何处理析构问题?上面的优雅的单例实现中,C++11规范规定,局部静态变量a,在第一次调用GetInstance函数时构造。由于a是static变量且未被初始化,会被直接放入.bss段,所以只要程序一加载,这段内存已经存在了,只是A类的构造函数还未被调用。当GetInstance被第一次调用时,a对象所占用的存储空间会被A的构造函数初始化。
对象a什么时候会被析构呢?
首先,A的析构函数由编译器插入的代码,在main函数退出之后调用。
其次,C++规范规定析构顺序一定是构造顺序的逆序。由于局部静态变量晚于全局变量被构造,所以局部静态变量晚于全局变量析构。全局变量析构也晚于gcc标签__attribute__((destructor))
定义的函数。所以顺序如下:
main ==> 局部静态变量 ==> __attribute__((destructor))
==> 全局变量。
析构引入的问题
这里最大的问题,就出在单例的对象。一个单例对象其实就是一个全局名字空间下的全局变量。而对于整个程序名字空间下的全局变量们的构造顺序,C++规范并没有明确说明。他依赖于编译,链接和库加载的顺序。请一定注意这一点。因为他打开了一个潘多拉魔盒,各种析构问题因此而生。
请设想这样一种情况,假如B依赖A的某种方法,但因为单例,B可以轻松避过与A建立构造依赖关系,如下:
class B{
public:
~B() {
A &a = A::GetInstance();
a.func();
}
};
B可能先于A构造也可能后于A构造。如果B的构造函数调用了A::GetInstance,那么A就先于B构造,且A后于B析构。上面的调用成立。
假如,B的构造没调用A::GetInstance,那么可能B析构中调用A的函数(例如:a.func()
)就会造成崩溃。解决这个问题的办法,很简单,请记住当类之间有依赖关系的时候,请用代码固化这个依赖关系。例如:
class B{
public:
B(A& a) {}; // <== 这一行确保了B依赖A,B构造的时候,A的单例已经构造好了
~B() {
A &a = A::GetInstance();
a.func();
}
};
虽然解决方法很简单,但其实很容易被忽略,因为人们都讨厌依赖和耦合。但别忘了显式依赖要远好于隐式依赖。如果要依赖就光明正大的做,不要暗戳戳的做,因为那是掩耳盗铃,而且会引入很多问题。
C++实现提供C语言接口引入的析构问题
这个问题才是最让人头疼的问题。因为C语言是无状态的,所以C语言的接口,可能在任意时候调用。例如:
void c_func() {
A &a = A::GetInstance();
a.func();
}
class D {
public:
~D() {
c_func();
}
}
现在D根本就不知道A的存在,他只知道c_func这个接口,因为class D和c_func是来自两个团队,甚至两个公司或两个社区。于是在某个程序里定义的D对象,在某个全局变量析构时调用了c_func,从而触发了a.func,而此时可能a已经释放了,因为a对象可能晚于D对象的构建,所以早于D对象析构。这是完全有可能的。
特别在A是一个复杂类的情况下,特别容易引入问题,而你一无所知。因为这个问题并不是一定发生,只是会碰巧发生,按照墨菲定律,往往是在最严重的时候发生。例如:
class A {
public:
static A& GetInstance() {
static A a;
return a;
}
private:
std::vector arr;
};
这里仅仅引入了一个std::vector,情况就会很严重。因为std::vector里有内存分配,这些内存都是malloc出来的。在vector析构的时候,这些内存毫无疑问会被释放。那么当A的单例在析构之后被调用的时候,虽然A本身的内存还在,但他的成员分配出的内存已经不在了。**一旦发生引用这些已释放的内存,行为就是不确定的。**coredump已经是比较好的结果了。如果没发生coredump,就会为产品留下一个漏洞,从而成为攻击的后门。
解法也有,但是代码会变的既啰嗦又丑陋。思路是,借用shared_ptr和weak_ptr的县城安全特性,实现析构时的内存保护。
class A { // 错误的示例,仅为阐述思路
public:
static std::shared_ptr<A> GetInstance() {
static std::shared_ptr<A> a = new A;
static std::weak_ptr<A> ref = a;
return ref.lock();
}
};
只可惜这段简洁的代码并不能完成我们的目标。因为std::weak_ptr<A> ref
也会被析构。而weak_ptr中的manager object是在构造时被new出来的,在weak_ptr析构时,会被释放(参考[1])。如果weak_ptr已经被析构,再调用ref.lock()
则会访问野指针。要解决ref析构以后访问的问题,代码就会变的很长。不在这里列出完整的代码了。给出思路:
class A {
public:
static std::shared_ptr<A> GetInstance() {
static std::shared_ptr<A> a = new A;
static MyWeakPtr<A> ref = a;
return ref.Acquire();
}
};
template<class T>
class MyWeakPtr {
public:
explicit MyWeakPtr(const std::shared_ptr<T> ptr) : destroyed(0), data(ptr){}
~MyWeakPtr() {
AtomicLockGuard lk(&destroyedLock);
destroyed = 1;
}
std::shared_ptr<T> Acquire() {
AtomicLockGuard lk(&destroyedLock);
if (!destoryed) { // line1
return data.lock(); // line2
}
return nullptr;
}
private:
int destroyed;
std::weak_ptr<T> data;
AtomicLock destroyedLock;
}
这里的核心思想是用自定义的MyWeakPtr替代标准库的weak_ptr。而自定义的MyWeakPtr除了std::weak_ptr外,不再含有任何堆上分配的内存。这也保证了析构后的安全访问。剩下的就是保证,weak_ptr析构后不再被访问到。思路是通过一个原子锁来保护一个析构的标志位。确保,析构后,weak_ptr不再被访问。
这里还有一个隐蔽的线程安全问题。
- 如果MyWeakPtr顺利拿到line1这一行的锁。如果weak_ptr在line1-line2之间进入析构,由于此时析构被原子锁阻挡,无法完成,weak_ptr的内存在析构完成之前是不会被释放的。所以line2可以在weak_ptr被析构前完成调用。因为shared_ptr先于weak_ptr构造,所以shared_ptr后于weak_ptr析构。所以此时shared_ptr必然还有效,所以可以通过weak_ptr锁住shared_ptr,使其不会被析构。
- 后续shared_ptr被析构后,由于析构顺序的关系,此时weak_ptr必然已完成析构函数,则代码执行会选择destructor==1的分支,而不会执行weak_ptr.lock操作。
综上所述,本实现是线程安全的。
另外一点值得注意的是,这里将GetInstance改为返回智能指针,即单例析构后的访问,可能返回nullptr,以示对象已经不存在了。但这样的设计势必会引起各处nullptr的判断,这里比较适合使用Null Object设计模式。
class A {
public:
static std::shared_ptr<A> GetInstance() {
static std::shared_ptr<A> a = new A;
static MyWeakPtr<A> ref = a;
auto b = ref.Acquire();
if (b == nullptr) {
return NullObjA::GetInstance();
}
return b;
}
};
...
};
class NullObjA : public A {
public:
void func() override {}
static GetInstance();
private:
static NullObjA nullA;
}
这里NullObjA不存在析构问题,因为这个对象里只有一个vptr,啥都没有,而这个指针是静态对象nullA的附属物,其占有的内存在nullA分配的时候分配,在nullA构造的时候,被赋值。而且nullA的内存是静态的全局数据区,是不会被释放的。所以对他的引用是安全的。
好了,到此算是把这个问题解掉了,对比一下代码,相比最优雅的Meyer's Singleton,这里已经多出很多行了。
Take Aways
- 如果是纯C++项目,请用依赖关系解决析构问题
- 如果是C/C++混编项目,请慎重提供全局对象(包括单例),尤其是复杂的全局对象。
- 如果非提供不可,请考虑线程安全和析构安全
参考文献
[1] C++ 智能指针(shared_ptr/weak_ptr)源码分析
[2] shared_ptr源码:shared_ptr_base.h, shared_ptr.h
[3] 当析构函数遇到多线程 ── C++ 中线程安全的对象回调
%5BTOC%5D%0A%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F%E6%9C%AC%E8%BA%AB%E5%BE%88%E7%AE%80%E5%8D%95%EF%BC%8C%E5%B0%B1%E6%98%AF%E4%B8%BA%E4%B8%80%E4%B8%AA%E7%B1%BB%E5%8F%AA%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1%E3%80%82%E5%B9%B6%E5%9C%A8%E5%85%A8%E5%B1%80%E5%BC%95%E7%94%A8%E8%BF%99%E4%B8%AA%E5%AF%B9%E8%B1%A1%E3%80%82%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F%E5%8C%85%E5%90%AB%E4%BA%86%E4%B8%A4%E5%B1%82%E6%B6%B5%E4%B9%89%EF%BC%9A%0A-%20%E4%B8%80%E4%B8%AA%E7%B1%BB%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AA%E5%AF%B9%E8%B1%A1%0A-%20%E8%BF%99%E4%B8%AA%E5%AF%B9%E8%B1%A1%E4%BC%9A%E8%A2%AB%E5%85%A8%E5%B1%80%E8%AE%BF%E9%97%AE%0A%E8%A6%81%E5%AE%9E%E7%8E%B0%E4%B8%80%E4%B8%AA%E7%AE%80%E5%8D%95%E7%9A%84%E5%8D%95%E4%BE%8B%E4%B9%9F%E5%BE%88%E5%AE%B9%E6%98%93%EF%BC%9A%0A%60%60%60c%2B%2B%0Aclass%20A%20%7B%0Apublic%3A%0A%20%20%20%20static%20A%20*GetInstance()%20%7B%0A%20%20%20%20%20%20%20%20if%20(a%20!%3D%20nullptr)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20a%20%3D%20new%20A%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20a%3B%0A%20%20%20%20%7D%0Aprivate%3A%0A%20%20%20%20A%20*a%3B%0A%7D%3B%0A%60%60%60%0A%E8%BF%99%E9%87%8C%E6%88%91%E6%95%85%E6%84%8F%E7%94%A8%E4%BA%86%E4%B8%80%E4%B8%AA%E5%8D%83%E7%96%AE%E7%99%BE%E5%AD%94%E7%9A%84%E5%8D%95%E4%BE%8B%E5%AE%9E%E7%8E%B0%E3%80%82%E4%B8%8B%E9%9D%A2%E6%88%91%E5%B0%B1%E5%88%97%E5%87%BA%E8%BF%99%E4%B8%AA%E5%8D%95%E4%BE%8B%E7%9A%84%E9%97%AE%E9%A2%98%E3%80%82%0A%23%20%E7%AE%80%E5%8D%95%E5%8D%95%E4%BE%8B%E7%9A%84%E9%97%AE%E9%A2%98%0A%23%23%20%E8%B0%81%E6%9D%A5%E9%87%8A%E6%94%BE%E8%BF%99%E4%B8%AA%E5%AF%B9%E8%B1%A1%EF%BC%9F%0A%E5%9B%A0%E4%B8%BAa%E6%98%AF%E4%B8%80%E4%B8%AA%E6%8C%87%E9%92%88%EF%BC%8C%E6%8C%87%E9%92%88%E5%8F%98%E9%87%8F%E6%98%AF%E4%B8%80%E4%B8%AAPOD%EF%BC%88plain%20of%20data%EF%BC%89%E5%8F%98%E9%87%8F%E3%80%82%E6%89%80%E4%BB%A5%E6%B2%A1%E6%9C%89%E4%BA%BA%E4%BC%9A%E5%B8%AE%E4%BD%A0%E8%B0%83%E7%94%A8A%E7%9A%84%E6%9E%90%E6%9E%84%E5%87%BD%E6%95%B0%E3%80%82%E8%BF%99%E5%8F%AF%E8%83%BD%E4%BC%9A%E9%80%A0%E6%88%90%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F%E3%80%82%E4%BD%86%E8%BF%9B%E7%A8%8B%E9%80%80%E5%87%BA%E6%97%B6%EF%BC%8C%E6%89%80%E6%9C%89%E8%AF%A5%E8%BF%9B%E7%A8%8B%E5%88%86%E9%85%8D%E7%9A%84%E5%86%85%E5%AD%98%E5%92%8C%E7%B3%BB%E7%BB%9F%E8%B5%84%E6%BA%90%E9%83%BD%E4%BC%9A%E8%A2%AB%E6%A0%87%E8%AE%B0%E6%88%90%E9%87%8A%E6%94%BE%E3%80%82%E4%BD%86%E5%A6%82%E6%9E%9C%E8%BF%99%E9%87%8C%E6%B6%89%E5%8F%8A%E5%88%B0%E7%BA%BF%E7%A8%8B%EF%BC%8C%E6%83%85%E5%86%B5%E4%BC%9A%E6%9C%89%E4%BA%9B%E8%AE%B8%E4%B8%8D%E5%90%8C%E3%80%82%E4%B8%80%E4%B8%AAjoinable%E7%BA%BF%E7%A8%8B%EF%BC%8C%E5%A6%82%E6%9E%9C%E4%B8%8D%E5%9C%A8%E8%BF%9B%E7%A8%8B%E7%BB%93%E6%9D%9F%E5%89%8Djoin%EF%BC%8C%E5%B0%B1%E4%BC%9A%E5%8F%91%E7%94%9F%E8%B5%84%E6%BA%90%E6%B3%84%E6%BC%8F%EF%BC%8C%E4%BA%A7%E7%94%9F%E5%83%B5%E5%B0%B8%E7%BA%BF%E7%A8%8B%E3%80%82%E4%BD%86%E8%BF%99%E4%B8%8D%E6%98%AF%E6%9C%AC%E6%96%87%E6%83%B3%E9%87%8D%E7%82%B9%E9%98%90%E8%BF%B0%E7%9A%84%E9%97%AE%E9%A2%98%E3%80%82%E5%9B%A0%E4%B8%BA%E9%87%8A%E6%94%BE%E8%BF%99%E7%A7%8D%E5%8D%95%E4%BE%8B%E5%86%85%E5%AD%98%E7%9A%84%E6%96%B9%E6%B3%95%E6%9C%89%E5%BE%88%E5%A4%9A%EF%BC%8C%E6%AF%94%E5%A6%82%EF%BC%9A%0A-%20%E5%AE%9A%E4%B9%89%E4%B8%80%E4%B8%AAdeletor%E7%B1%BB%EF%BC%8C%E5%86%8D%E5%AE%9A%E4%B9%89%E4%B8%80%E4%B8%AAstatic%E7%9A%84deletor%E5%AF%B9%E8%B1%A1%EF%BC%8C%E5%B9%B6%E5%9C%A8deletor%E5%AF%B9%E8%B1%A1%E4%B8%AD%E9%87%8A%E6%94%BEa%0A-%20%E7%9B%B4%E6%8E%A5%E7%94%A8%E5%B1%80%E9%83%A8%E9%9D%99%E6%80%81%E5%8F%98%E9%87%8F%0A-%20%E6%88%96%E8%80%85%E5%B0%86%60A%20*a%60%E5%AE%9A%E4%B9%89%E6%88%90%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88%0A%0A%23%23%20%E5%A6%82%E4%BD%95%E5%A4%84%E7%90%86%E5%B9%B6%E5%8F%91%EF%BC%9F%0A%E5%A6%82%E6%9E%9CGetInstance%E5%87%BD%E6%95%B0%E8%A2%AB%E5%B9%B6%E5%8F%91%E8%AE%BF%E9%97%AE%EF%BC%8C%E4%B8%8A%E9%9D%A2%E7%9A%84%E7%AE%80%E5%8D%95%E5%8D%95%E4%BE%8B%E5%AE%9E%E7%8E%B0%E4%BC%9A%E6%9C%89%E5%B9%B6%E5%8F%91%E9%97%AE%E9%A2%98%E3%80%82%E5%8D%B3a%E5%8F%AF%E8%83%BD%E8%A2%AB%E9%87%8D%E5%A4%8D%E8%B5%8B%E5%80%BC%EF%BC%8C%E4%BB%8E%E8%80%8C%E4%BA%A7%E7%94%9F%E4%BA%86%E5%87%A0%E4%B8%AA%E9%87%8E%E5%AF%B9%E8%B1%A1%E3%80%82%E8%A7%A3%E5%86%B3%E8%BF%99%E4%B8%AA%E9%97%AE%E9%A2%98%E6%AF%94%E8%BE%83%E4%BC%98%E9%9B%85%E7%82%B9%E7%9A%84%E5%8A%9E%E6%B3%95%E5%B0%B1%E6%98%AF%E7%94%A8%60std%3A%3Acall_once%60%EF%BC%8C%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%60%60%60c%2B%2B%0Aclass%20A%20%7B%0Apublic%3A%0A%20%20%20%20static%20A%26%20GetInstance()%20%7B%0A%20%20%20%20%20%20%20%20std%3A%3Aonce_flag%20flag%3B%0A%20%20%20%20%20%20%20%20std%3A%3Acall_once(flag%2C%20%5B%5D()(%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(a%20!%3D%20nullptr)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20a%20%3D%20new%20A%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D)%3B%0A%20%20%20%20%20%20%20%20return%20*a%3B%0A%20%20%20%20%7D%0Aprivate%3A%0A%20%20%20%20A%20*a%3B%0A%7D%3B%0A%60%60%60%0A%E8%BF%99%E9%87%8C%E8%BF%94%E5%9B%9E%E5%80%BC%E4%BB%8E%E6%8C%87%E9%92%88%EF%BC%8C%E5%8F%98%E6%88%90%E4%BA%86%E5%BC%95%E7%94%A8%E3%80%82%E8%A8%80%E4%B8%8B%E4%B9%8B%E6%84%8F%EF%BC%8C%E5%8D%95%E4%BE%8B%E7%9A%84%E8%8E%B7%E5%8F%96%E5%9C%A8%E7%A8%8B%E5%BA%8F%E6%95%B4%E4%B8%AA%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%86%85%E4%BB%8E%E6%9D%A5%E4%B8%8D%E4%BC%9A%E5%A4%B1%E8%B4%A5%E3%80%82%E4%B8%8D%E8%BF%87%E8%BF%99%E6%98%AF%E7%90%86%E6%83%B3%E7%8A%B6%E5%86%B5%EF%BC%8C%E5%9C%A8%E6%9F%90%E4%BA%9B%E6%A8%A1%E5%9E%8B%E4%B8%8B%EF%BC%8C%E6%88%91%E4%BB%AC%E4%B8%8D%E5%BE%97%E4%B8%8D%E8%AE%A9%E5%8D%95%E4%BE%8B%E8%BF%94%E5%9B%9E%E7%A9%BA%E6%8C%87%E9%92%88%E3%80%82%0A%E5%8F%A6%E5%A4%96%EF%BC%8CC%2B%2B11%E7%9A%84%E8%AF%AD%E8%A8%80%E8%A7%84%E8%8C%83%E5%AE%9A%E4%B9%89%E4%BA%86%E5%B1%80%E9%83%A8%E9%9D%99%E6%80%81%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%9E%84%E9%80%A0%E6%9E%90%E6%9E%84%E8%A1%8C%E4%B8%BA%EF%BC%8C%E7%A1%AE%E4%BF%9D%E5%85%B6%E5%8F%AA%E4%BC%9A%E8%A2%AB%E6%9E%84%E9%80%A0%E4%B8%80%E6%AC%A1%E3%80%82%E6%89%80%E4%BB%A5%E5%9C%A8C%2B%2B11%E5%8F%8A%E4%BB%A5%E4%B8%8A%E7%9A%84%E5%9C%BA%E6%99%AF%E4%B8%8B%EF%BC%8C%E6%9C%80%E4%BC%98%E9%9B%85%E7%9A%84%E4%BB%A3%E7%A0%81%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%60%60%60c%2B%2B%0Aclass%20A%20%7B%0Apublic%3A%0A%20%20%20%20A%26%20GetInstance()%20%7B%0A%20%20%20%20%20%20%20%20static%20A%20a%3B%0A%20%20%20%20%20%20%20%20return%20a%3B%0A%20%20%20%20%7D%0A%7D%3B%0A%60%60%60%0A%E8%BF%99%E5%B0%B1%E6%98%AF%E8%91%97%E5%90%8D%E7%9A%84Meyer's%20Singleton%EF%BC%8C%E6%97%A2%E7%AE%80%E6%B4%81%E5%8F%88%E4%B8%8D%E4%BC%9A%E7%8A%AF%E9%94%99%EF%BC%8C%E5%8F%AF%E6%83%9C%E5%8F%AA%E8%83%BD%E7%94%A8%E4%BA%8EC%2B%2B11%E4%BB%A5%E5%90%8E%E7%9A%84%E7%89%88%E6%9C%AC%E3%80%82%0A%0A%23%23%20%E6%9E%90%E6%9E%84%E9%A1%BA%E5%BA%8F%EF%BC%9F%0A%E5%8F%AF%E4%BB%A5%E5%BC%95%E5%87%BA%E4%BB%8A%E5%A4%A9%E7%9A%84%E4%B8%BB%E8%A7%92%E4%BA%86%E3%80%82%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F%E5%A6%82%E4%BD%95%E5%A4%84%E7%90%86%E6%9E%90%E6%9E%84%E9%97%AE%E9%A2%98%EF%BC%9F%E4%B8%8A%E9%9D%A2%E7%9A%84%E4%BC%98%E9%9B%85%E7%9A%84%E5%8D%95%E4%BE%8B%E5%AE%9E%E7%8E%B0%E4%B8%AD%EF%BC%8CC%2B%2B11%E8%A7%84%E8%8C%83%E8%A7%84%E5%AE%9A%EF%BC%8C%E5%B1%80%E9%83%A8%E9%9D%99%E6%80%81%E5%8F%98%E9%87%8Fa%EF%BC%8C%E5%9C%A8%E7%AC%AC%E4%B8%80%E6%AC%A1%E8%B0%83%E7%94%A8GetInstance%E5%87%BD%E6%95%B0%E6%97%B6%E6%9E%84%E9%80%A0%E3%80%82%E7%94%B1%E4%BA%8Ea%E6%98%AFstatic%E5%8F%98%E9%87%8F%E4%B8%94%E6%9C%AA%E8%A2%AB%E5%88%9D%E5%A7%8B%E5%8C%96%EF%BC%8C%E4%BC%9A%E8%A2%AB%E7%9B%B4%E6%8E%A5%E6%94%BE%E5%85%A5.bss%E6%AE%B5%EF%BC%8C%E6%89%80%E4%BB%A5%E5%8F%AA%E8%A6%81%E7%A8%8B%E5%BA%8F%E4%B8%80%E5%8A%A0%E8%BD%BD%EF%BC%8C%E8%BF%99%E6%AE%B5%E5%86%85%E5%AD%98%E5%B7%B2%E7%BB%8F%E5%AD%98%E5%9C%A8%E4%BA%86%EF%BC%8C%E5%8F%AA%E6%98%AFA%E7%B1%BB%E7%9A%84%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E8%BF%98%E6%9C%AA%E8%A2%AB%E8%B0%83%E7%94%A8%E3%80%82%E5%BD%93GetInstance%E8%A2%AB%E7%AC%AC%E4%B8%80%E6%AC%A1%E8%B0%83%E7%94%A8%E6%97%B6%EF%BC%8Ca%E5%AF%B9%E8%B1%A1%E6%89%80%E5%8D%A0%E7%94%A8%E7%9A%84%E5%AD%98%E5%82%A8%E7%A9%BA%E9%97%B4%E4%BC%9A%E8%A2%ABA%E7%9A%84%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E5%88%9D%E5%A7%8B%E5%8C%96%E3%80%82%0A%0A%23%23%23%20%E5%AF%B9%E8%B1%A1a%E4%BB%80%E4%B9%88%E6%97%B6%E5%80%99%E4%BC%9A%E8%A2%AB%E6%9E%90%E6%9E%84%E5%91%A2%EF%BC%9F%0A%E9%A6%96%E5%85%88%EF%BC%8CA%E7%9A%84%E6%9E%90%E6%9E%84%E5%87%BD%E6%95%B0%E7%94%B1%E7%BC%96%E8%AF%91%E5%99%A8%E6%8F%92%E5%85%A5%E7%9A%84%E4%BB%A3%E7%A0%81%EF%BC%8C%E5%9C%A8main%E5%87%BD%E6%95%B0%E9%80%80%E5%87%BA%E4%B9%8B%E5%90%8E%E8%B0%83%E7%94%A8%E3%80%82%0A%E5%85%B6%E6%AC%A1%EF%BC%8CC%2B%2B%E8%A7%84%E8%8C%83%E8%A7%84%E5%AE%9A%E6%9E%90%E6%9E%84%E9%A1%BA%E5%BA%8F%E4%B8%80%E5%AE%9A%E6%98%AF%E6%9E%84%E9%80%A0%E9%A1%BA%E5%BA%8F%E7%9A%84%E9%80%86%E5%BA%8F%E3%80%82%E7%94%B1%E4%BA%8E%E5%B1%80%E9%83%A8%E9%9D%99%E6%80%81%E5%8F%98%E9%87%8F%E6%99%9A%E4%BA%8E%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%E8%A2%AB%E6%9E%84%E9%80%A0%EF%BC%8C%E6%89%80%E4%BB%A5%E5%B1%80%E9%83%A8%E9%9D%99%E6%80%81%E5%8F%98%E9%87%8F%E6%99%9A%E4%BA%8E%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%E6%9E%90%E6%9E%84%E3%80%82%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%E6%9E%90%E6%9E%84%E4%B9%9F%E6%99%9A%E4%BA%8Egcc%E6%A0%87%E7%AD%BE%60__attribute__((destructor))%60%E5%AE%9A%E4%B9%89%E7%9A%84%E5%87%BD%E6%95%B0%E3%80%82%E6%89%80%E4%BB%A5%E9%A1%BA%E5%BA%8F%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%3Emain%20%3D%3D%3E%20%E5%B1%80%E9%83%A8%E9%9D%99%E6%80%81%E5%8F%98%E9%87%8F%20%3D%3D%3E%20%60__attribute__((destructor))%60%20%3D%3D%3E%20%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%E3%80%82%0A%0A%23%23%23%20%E6%9E%90%E6%9E%84%E5%BC%95%E5%85%A5%E7%9A%84%E9%97%AE%E9%A2%98%0A%E8%BF%99%E9%87%8C%E6%9C%80%E5%A4%A7%E7%9A%84%E9%97%AE%E9%A2%98%EF%BC%8C%E5%B0%B1%E5%87%BA%E5%9C%A8%E5%8D%95%E4%BE%8B%E7%9A%84%E5%AF%B9%E8%B1%A1%E3%80%82%E4%B8%80%E4%B8%AA%E5%8D%95%E4%BE%8B%E5%AF%B9%E8%B1%A1%E5%85%B6%E5%AE%9E%E5%B0%B1%E6%98%AF%E4%B8%80%E4%B8%AA%E5%85%A8%E5%B1%80%E5%90%8D%E5%AD%97%E7%A9%BA%E9%97%B4%E4%B8%8B%E7%9A%84%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%E3%80%82%E8%80%8C%E5%AF%B9%E4%BA%8E%E6%95%B4%E4%B8%AA%E7%A8%8B%E5%BA%8F%E5%90%8D%E5%AD%97%E7%A9%BA%E9%97%B4%E4%B8%8B%E7%9A%84%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%E4%BB%AC%E7%9A%84%E6%9E%84%E9%80%A0%E9%A1%BA%E5%BA%8F%EF%BC%8CC%2B%2B%E8%A7%84%E8%8C%83%E5%B9%B6%E6%B2%A1%E6%9C%89%E6%98%8E%E7%A1%AE%E8%AF%B4%E6%98%8E%E3%80%82%E4%BB%96%E4%BE%9D%E8%B5%96%E4%BA%8E%E7%BC%96%E8%AF%91%EF%BC%8C%E9%93%BE%E6%8E%A5%E5%92%8C%E5%BA%93%E5%8A%A0%E8%BD%BD%E7%9A%84%E9%A1%BA%E5%BA%8F%E3%80%82%E8%AF%B7%E4%B8%80%E5%AE%9A%E6%B3%A8%E6%84%8F%E8%BF%99%E4%B8%80%E7%82%B9%E3%80%82%E5%9B%A0%E4%B8%BA%E4%BB%96%E6%89%93%E5%BC%80%E4%BA%86%E4%B8%80%E4%B8%AA%E6%BD%98%E5%A4%9A%E6%8B%89%E9%AD%94%E7%9B%92%EF%BC%8C%E5%90%84%E7%A7%8D%E6%9E%90%E6%9E%84%E9%97%AE%E9%A2%98%E5%9B%A0%E6%AD%A4%E8%80%8C%E7%94%9F%E3%80%82%0A%E8%AF%B7%E8%AE%BE%E6%83%B3%E8%BF%99%E6%A0%B7%E4%B8%80%E7%A7%8D%E6%83%85%E5%86%B5%EF%BC%8C%E5%81%87%E5%A6%82B%E4%BE%9D%E8%B5%96A%E7%9A%84%E6%9F%90%E7%A7%8D%E6%96%B9%E6%B3%95%EF%BC%8C%E4%BD%86%E5%9B%A0%E4%B8%BA%E5%8D%95%E4%BE%8B%EF%BC%8CB%E5%8F%AF%E4%BB%A5%E8%BD%BB%E6%9D%BE%E9%81%BF%E8%BF%87%E4%B8%8EA%E5%BB%BA%E7%AB%8B%E6%9E%84%E9%80%A0%E4%BE%9D%E8%B5%96%E5%85%B3%E7%B3%BB%EF%BC%8C%E5%A6%82%E4%B8%8B%EF%BC%9A%0A%60%60%60c%2B%2B%0Aclass%20B%7B%0Apublic%3A%0A%20%20%20%20%EF%BD%9EB()%20%7B%0A%20%20%20%20%20%20%20%20A%20%26a%20%3D%20A%3A%3AGetInstance()%3B%0A%20%20%20%20%20%20%20%20a.func()%3B%0A%20%20%20%20%7D%0A%7D%3B%0A%60%60%60%0AB%E5%8F%AF%E8%83%BD%E5%85%88%E4%BA%8EA%E6%9E%84%E9%80%A0%E4%B9%9F%E5%8F%AF%E8%83%BD%E5%90%8E%E4%BA%8EA%E6%9E%84%E9%80%A0%E3%80%82%E5%A6%82%E6%9E%9CB%E7%9A%84%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E8%B0%83%E7%94%A8%E4%BA%86A%3A%3AGetInstance%EF%BC%8C%E9%82%A3%E4%B9%88A%E5%B0%B1%E5%85%88%E4%BA%8EB%E6%9E%84%E9%80%A0%EF%BC%8C%E4%B8%94A%E5%90%8E%E4%BA%8EB%E6%9E%90%E6%9E%84%E3%80%82%E4%B8%8A%E9%9D%A2%E7%9A%84%E8%B0%83%E7%94%A8%E6%88%90%E7%AB%8B%E3%80%82%0A%E5%81%87%E5%A6%82%EF%BC%8CB%E7%9A%84%E6%9E%84%E9%80%A0%E6%B2%A1%E8%B0%83%E7%94%A8A%3A%3AGetInstance%EF%BC%8C%E9%82%A3%E4%B9%88%E5%8F%AF%E8%83%BDB%E6%9E%90%E6%9E%84%E4%B8%AD%E8%B0%83%E7%94%A8A%E7%9A%84%E5%87%BD%E6%95%B0%EF%BC%88%E4%BE%8B%E5%A6%82%EF%BC%9A%60a.func()%60%EF%BC%89%E5%B0%B1%E4%BC%9A%E9%80%A0%E6%88%90%E5%B4%A9%E6%BA%83%E3%80%82%E8%A7%A3%E5%86%B3%E8%BF%99%E4%B8%AA%E9%97%AE%E9%A2%98%E7%9A%84%E5%8A%9E%E6%B3%95%EF%BC%8C%E5%BE%88%E7%AE%80%E5%8D%95%EF%BC%8C%E8%AF%B7%E8%AE%B0%E4%BD%8F**%E5%BD%93%E7%B1%BB%E4%B9%8B%E9%97%B4%E6%9C%89%E4%BE%9D%E8%B5%96%E5%85%B3%E7%B3%BB%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8C%E8%AF%B7%E7%94%A8%E4%BB%A3%E7%A0%81%E5%9B%BA%E5%8C%96%E8%BF%99%E4%B8%AA%E4%BE%9D%E8%B5%96%E5%85%B3%E7%B3%BB**%E3%80%82%E4%BE%8B%E5%A6%82%EF%BC%9A%0A%60%60%60c%2B%2B%0Aclass%20B%7B%0Apublic%3A%0A%20%20%20%20B(A%26%20a)%20%7B%7D%3B%20%2F%2F%20%3C%3D%3D%20%E8%BF%99%E4%B8%80%E8%A1%8C%E7%A1%AE%E4%BF%9D%E4%BA%86B%E4%BE%9D%E8%B5%96A%EF%BC%8CB%E6%9E%84%E9%80%A0%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8CA%E7%9A%84%E5%8D%95%E4%BE%8B%E5%B7%B2%E7%BB%8F%E6%9E%84%E9%80%A0%E5%A5%BD%E4%BA%86%0A%20%20%20%20%EF%BD%9EB()%20%7B%0A%20%20%20%20%20%20%20%20A%20%26a%20%3D%20A%3A%3AGetInstance()%3B%0A%20%20%20%20%20%20%20%20a.func()%3B%0A%20%20%20%20%7D%0A%7D%3B%0A%60%60%60%0A%E8%99%BD%E7%84%B6%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95%E5%BE%88%E7%AE%80%E5%8D%95%EF%BC%8C%E4%BD%86%E5%85%B6%E5%AE%9E%E5%BE%88%E5%AE%B9%E6%98%93%E8%A2%AB%E5%BF%BD%E7%95%A5%EF%BC%8C%E5%9B%A0%E4%B8%BA%E4%BA%BA%E4%BB%AC%E9%83%BD%E8%AE%A8%E5%8E%8C%E4%BE%9D%E8%B5%96%E5%92%8C%E8%80%A6%E5%90%88%E3%80%82%E4%BD%86%E5%88%AB%E5%BF%98%E4%BA%86%E6%98%BE%E5%BC%8F%E4%BE%9D%E8%B5%96%E8%A6%81%E8%BF%9C%E5%A5%BD%E4%BA%8E%E9%9A%90%E5%BC%8F%E4%BE%9D%E8%B5%96%E3%80%82%E5%A6%82%E6%9E%9C%E8%A6%81%E4%BE%9D%E8%B5%96%E5%B0%B1%E5%85%89%E6%98%8E%E6%AD%A3%E5%A4%A7%E7%9A%84%E5%81%9A%EF%BC%8C%E4%B8%8D%E8%A6%81%E6%9A%97%E6%88%B3%E6%88%B3%E7%9A%84%E5%81%9A%EF%BC%8C%E5%9B%A0%E4%B8%BA%E9%82%A3%E6%98%AF%E6%8E%A9%E8%80%B3%E7%9B%97%E9%93%83%EF%BC%8C%E8%80%8C%E4%B8%94%E4%BC%9A%E5%BC%95%E5%85%A5%E5%BE%88%E5%A4%9A%E9%97%AE%E9%A2%98%E3%80%82%0A%0A%23%23%23%20C%2B%2B%E5%AE%9E%E7%8E%B0%E6%8F%90%E4%BE%9BC%E8%AF%AD%E8%A8%80%E6%8E%A5%E5%8F%A3%E5%BC%95%E5%85%A5%E7%9A%84%E6%9E%90%E6%9E%84%E9%97%AE%E9%A2%98%0A%E8%BF%99%E4%B8%AA%E9%97%AE%E9%A2%98%E6%89%8D%E6%98%AF%E6%9C%80%E8%AE%A9%E4%BA%BA%E5%A4%B4%E7%96%BC%E7%9A%84%E9%97%AE%E9%A2%98%E3%80%82%E5%9B%A0%E4%B8%BAC%E8%AF%AD%E8%A8%80%E6%98%AF%E6%97%A0%E7%8A%B6%E6%80%81%E7%9A%84%EF%BC%8C%E6%89%80%E4%BB%A5C%E8%AF%AD%E8%A8%80%E7%9A%84%E6%8E%A5%E5%8F%A3%EF%BC%8C%E5%8F%AF%E8%83%BD%E5%9C%A8%E4%BB%BB%E6%84%8F%E6%97%B6%E5%80%99%E8%B0%83%E7%94%A8%E3%80%82%E4%BE%8B%E5%A6%82%EF%BC%9A%0A%60%60%60c%2B%2B%0Avoid%20c_func()%20%7B%0A%20%20%20%20A%20%26a%20%3D%20A%3A%3AGetInstance()%3B%0A%20%20%20%20a.func()%3B%0A%7D%0A%0Aclass%20D%20%7B%0Apublic%3A%0A%20%20%20%20~D()%20%7B%0A%20%20%20%20%20%20%20%20c_func()%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%E7%8E%B0%E5%9C%A8D%E6%A0%B9%E6%9C%AC%E5%B0%B1%E4%B8%8D%E7%9F%A5%E9%81%93A%E7%9A%84%E5%AD%98%E5%9C%A8%EF%BC%8C%E4%BB%96%E5%8F%AA%E7%9F%A5%E9%81%93c_func%E8%BF%99%E4%B8%AA%E6%8E%A5%E5%8F%A3%EF%BC%8C%E5%9B%A0%E4%B8%BAclass%20D%E5%92%8Cc_func%E6%98%AF%E6%9D%A5%E8%87%AA%E4%B8%A4%E4%B8%AA%E5%9B%A2%E9%98%9F%EF%BC%8C%E7%94%9A%E8%87%B3%E4%B8%A4%E4%B8%AA%E5%85%AC%E5%8F%B8%E6%88%96%E4%B8%A4%E4%B8%AA%E7%A4%BE%E5%8C%BA%E3%80%82%E4%BA%8E%E6%98%AF%E5%9C%A8%E6%9F%90%E4%B8%AA%E7%A8%8B%E5%BA%8F%E9%87%8C%E5%AE%9A%E4%B9%89%E7%9A%84D%E5%AF%B9%E8%B1%A1%EF%BC%8C%E5%9C%A8%E6%9F%90%E4%B8%AA%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%E6%9E%90%E6%9E%84%E6%97%B6%E8%B0%83%E7%94%A8%E4%BA%86c_func%EF%BC%8C%E4%BB%8E%E8%80%8C%E8%A7%A6%E5%8F%91%E4%BA%86a.func%EF%BC%8C%E8%80%8C%E6%AD%A4%E6%97%B6%E5%8F%AF%E8%83%BDa%E5%B7%B2%E7%BB%8F%E9%87%8A%E6%94%BE%E4%BA%86%EF%BC%8C%E5%9B%A0%E4%B8%BAa%E5%AF%B9%E8%B1%A1%E5%8F%AF%E8%83%BD%E6%99%9A%E4%BA%8ED%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%9E%84%E5%BB%BA%EF%BC%8C%E6%89%80%E4%BB%A5%E6%97%A9%E4%BA%8ED%E5%AF%B9%E8%B1%A1%E6%9E%90%E6%9E%84%E3%80%82%E8%BF%99%E6%98%AF%E5%AE%8C%E5%85%A8%E6%9C%89%E5%8F%AF%E8%83%BD%E7%9A%84%E3%80%82%0A**%E7%89%B9%E5%88%AB%E5%9C%A8A%E6%98%AF%E4%B8%80%E4%B8%AA%E5%A4%8D%E6%9D%82%E7%B1%BB%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B**%EF%BC%8C%E7%89%B9%E5%88%AB%E5%AE%B9%E6%98%93%E5%BC%95%E5%85%A5%E9%97%AE%E9%A2%98%EF%BC%8C%E8%80%8C%E4%BD%A0%E4%B8%80%E6%97%A0%E6%89%80%E7%9F%A5%E3%80%82%E5%9B%A0%E4%B8%BA%E8%BF%99%E4%B8%AA%E9%97%AE%E9%A2%98%E5%B9%B6%E4%B8%8D%E6%98%AF%E4%B8%80%E5%AE%9A%E5%8F%91%E7%94%9F%EF%BC%8C%E5%8F%AA%E6%98%AF%E4%BC%9A%E7%A2%B0%E5%B7%A7%E5%8F%91%E7%94%9F%EF%BC%8C%E6%8C%89%E7%85%A7%E5%A2%A8%E8%8F%B2%E5%AE%9A%E5%BE%8B%EF%BC%8C%E5%BE%80%E5%BE%80%E6%98%AF%E5%9C%A8%E6%9C%80%E4%B8%A5%E9%87%8D%E7%9A%84%E6%97%B6%E5%80%99%E5%8F%91%E7%94%9F%E3%80%82%E4%BE%8B%E5%A6%82%EF%BC%9A%0A%60%60%60c%2B%2B%0Aclass%20A%20%7B%0Apublic%3A%0A%20%20%20%20static%20A%26%20GetInstance()%20%7B%0A%20%20%20%20%20%20%20%20static%20A%20a%3B%0A%20%20%20%20%20%20%20%20return%20a%3B%0A%20%20%20%20%7D%0Aprivate%3A%0A%20%20%20%20std%3A%3Avector%20arr%3B%0A%7D%3B%0A%60%60%60%0A%E8%BF%99%E9%87%8C%E4%BB%85%E4%BB%85%E5%BC%95%E5%85%A5%E4%BA%86%E4%B8%80%E4%B8%AAstd%3A%3Avector%EF%BC%8C%E6%83%85%E5%86%B5%E5%B0%B1%E4%BC%9A%E5%BE%88%E4%B8%A5%E9%87%8D%E3%80%82%E5%9B%A0%E4%B8%BAstd%3A%3Avector%E9%87%8C%E6%9C%89%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D%EF%BC%8C%E8%BF%99%E4%BA%9B%E5%86%85%E5%AD%98%E9%83%BD%E6%98%AFmalloc%E5%87%BA%E6%9D%A5%E7%9A%84%E3%80%82%E5%9C%A8vector%E6%9E%90%E6%9E%84%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8C%E8%BF%99%E4%BA%9B%E5%86%85%E5%AD%98%E6%AF%AB%E6%97%A0%E7%96%91%E9%97%AE%E4%BC%9A%E8%A2%AB%E9%87%8A%E6%94%BE%E3%80%82%E9%82%A3%E4%B9%88%E5%BD%93A%E7%9A%84%E5%8D%95%E4%BE%8B%E5%9C%A8%E6%9E%90%E6%9E%84%E4%B9%8B%E5%90%8E%E8%A2%AB%E8%B0%83%E7%94%A8%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8C%E8%99%BD%E7%84%B6A%E6%9C%AC%E8%BA%AB%E7%9A%84%E5%86%85%E5%AD%98%E8%BF%98%E5%9C%A8%EF%BC%8C%E4%BD%86%E4%BB%96%E7%9A%84%E6%88%90%E5%91%98%E5%88%86%E9%85%8D%E5%87%BA%E7%9A%84%E5%86%85%E5%AD%98%E5%B7%B2%E7%BB%8F%E4%B8%8D%E5%9C%A8%E4%BA%86%E3%80%82**%E4%B8%80%E6%97%A6%E5%8F%91%E7%94%9F%E5%BC%95%E7%94%A8%E8%BF%99%E4%BA%9B%E5%B7%B2%E9%87%8A%E6%94%BE%E7%9A%84%E5%86%85%E5%AD%98%EF%BC%8C%E8%A1%8C%E4%B8%BA%E5%B0%B1%E6%98%AF%E4%B8%8D%E7%A1%AE%E5%AE%9A%E7%9A%84%E3%80%82**coredump%E5%B7%B2%E7%BB%8F%E6%98%AF%E6%AF%94%E8%BE%83%E5%A5%BD%E7%9A%84%E7%BB%93%E6%9E%9C%E4%BA%86%E3%80%82%E5%A6%82%E6%9E%9C%E6%B2%A1%E5%8F%91%E7%94%9Fcoredump%EF%BC%8C%E5%B0%B1%E4%BC%9A%E4%B8%BA%E4%BA%A7%E5%93%81%E7%95%99%E4%B8%8B%E4%B8%80%E4%B8%AA%E6%BC%8F%E6%B4%9E%EF%BC%8C%E4%BB%8E%E8%80%8C%E6%88%90%E4%B8%BA%E6%94%BB%E5%87%BB%E7%9A%84%E5%90%8E%E9%97%A8%E3%80%82%0A%0A%E8%A7%A3%E6%B3%95%E4%B9%9F%E6%9C%89%EF%BC%8C%E4%BD%86%E6%98%AF%E4%BB%A3%E7%A0%81%E4%BC%9A%E5%8F%98%E7%9A%84%E6%97%A2%E5%95%B0%E5%97%A6%E5%8F%88%E4%B8%91%E9%99%8B%E3%80%82%E6%80%9D%E8%B7%AF%E6%98%AF%EF%BC%8C%E5%80%9F%E7%94%A8shared_ptr%E5%92%8Cweak_ptr%E7%9A%84%E5%8E%BF%E5%9F%8E%E5%AE%89%E5%85%A8%E7%89%B9%E6%80%A7%EF%BC%8C%E5%AE%9E%E7%8E%B0%E6%9E%90%E6%9E%84%E6%97%B6%E7%9A%84%E5%86%85%E5%AD%98%E4%BF%9D%E6%8A%A4%E3%80%82%0A%60%60%60c%2B%2B%0Aclass%20A%20%7B%20%2F%2F%20%E9%94%99%E8%AF%AF%E7%9A%84%E7%A4%BA%E4%BE%8B%EF%BC%8C%E4%BB%85%E4%B8%BA%E9%98%90%E8%BF%B0%E6%80%9D%E8%B7%AF%0Apublic%3A%0A%20%20%20%20static%20std%3A%3Ashared_ptr%3CA%3E%20GetInstance()%20%7B%0A%20%20%20%20%20%20%20%20static%20std%3A%3Ashared_ptr%3CA%3E%20a%20%3D%20new%20A%3B%0A%20%20%20%20%20%20%20%20static%20std%3A%3Aweak_ptr%3CA%3E%20ref%20%3D%20a%3B%0A%20%20%20%20%20%20%20%20return%20ref.lock()%3B%0A%20%20%20%20%7D%0A%7D%3B%0A%60%60%60%0A%E5%8F%AA%E5%8F%AF%E6%83%9C%E8%BF%99%E6%AE%B5%E7%AE%80%E6%B4%81%E7%9A%84%E4%BB%A3%E7%A0%81%E5%B9%B6%E4%B8%8D%E8%83%BD%E5%AE%8C%E6%88%90%E6%88%91%E4%BB%AC%E7%9A%84%E7%9B%AE%E6%A0%87%E3%80%82%E5%9B%A0%E4%B8%BA%60std%3A%3Aweak_ptr%3CA%3E%20ref%60%E4%B9%9F%E4%BC%9A%E8%A2%AB%E6%9E%90%E6%9E%84%E3%80%82%E8%80%8Cweak_ptr%E4%B8%AD%E7%9A%84manager%20object%E6%98%AF%E5%9C%A8%E6%9E%84%E9%80%A0%E6%97%B6%E8%A2%ABnew%E5%87%BA%E6%9D%A5%E7%9A%84%EF%BC%8C%E5%9C%A8weak_ptr%E6%9E%90%E6%9E%84%E6%97%B6%EF%BC%8C%E4%BC%9A%E8%A2%AB%E9%87%8A%E6%94%BE(%E5%8F%82%E8%80%83%5B1%5D)%E3%80%82%E5%A6%82%E6%9E%9Cweak_ptr%E5%B7%B2%E7%BB%8F%E8%A2%AB%E6%9E%90%E6%9E%84%EF%BC%8C%E5%86%8D%E8%B0%83%E7%94%A8%60ref.lock()%60%E5%88%99%E4%BC%9A%E8%AE%BF%E9%97%AE%E9%87%8E%E6%8C%87%E9%92%88%E3%80%82%E8%A6%81%E8%A7%A3%E5%86%B3ref%E6%9E%90%E6%9E%84%E4%BB%A5%E5%90%8E%E8%AE%BF%E9%97%AE%E7%9A%84%E9%97%AE%E9%A2%98%EF%BC%8C%E4%BB%A3%E7%A0%81%E5%B0%B1%E4%BC%9A%E5%8F%98%E7%9A%84%E5%BE%88%E9%95%BF%E3%80%82%E4%B8%8D%E5%9C%A8%E8%BF%99%E9%87%8C%E5%88%97%E5%87%BA%E5%AE%8C%E6%95%B4%E7%9A%84%E4%BB%A3%E7%A0%81%E4%BA%86%E3%80%82%E7%BB%99%E5%87%BA%E6%80%9D%E8%B7%AF%EF%BC%9A%0A%60%60%60c%2B%2B%0Aclass%20A%20%7B%0Apublic%3A%0A%20%20%20%20static%20std%3A%3Ashared_ptr%3CA%3E%20GetInstance()%20%7B%0A%20%20%20%20%20%20%20%20static%20std%3A%3Ashared_ptr%3CA%3E%20a%20%3D%20new%20A%3B%0A%20%20%20%20%20%20%20%20static%20MyWeakPtr%3CA%3E%20ref%20%3D%20a%3B%0A%20%20%20%20%20%20%20%20return%20ref.Acquire()%3B%0A%20%20%20%20%7D%0A%7D%3B%0A%0Atemplate%3Cclass%20T%3E%0Aclass%20MyWeakPtr%20%7B%0Apublic%3A%0A%20%20%20%20explicit%20MyWeakPtr(const%20std%3A%3Ashared_ptr%3CT%3E%20ptr)%20%3A%20destroyed(0)%2C%20data(ptr)%7B%7D%0A%20%20%20%20~MyWeakPtr()%20%7B%0A%20%20%20%20%20%20%20%20AtomicLockGuard%20lk(%26destroyedLock)%3B%0A%20%20%20%20%20%20%20%20destroyed%20%3D%201%3B%0A%20%20%20%20%7D%0A%20%20%20%20%0A%20%20%20%20std%3A%3Ashared_ptr%3CT%3E%20Acquire()%20%7B%0A%20%20%20%20%20%20%20%20AtomicLockGuard%20lk(%26destroyedLock)%3B%0A%20%20%20%20%20%20%20%20if%20(!destoryed)%20%7B%20%2F%2F%20line1%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20data.lock()%3B%20%2F%2F%20line2%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20nullptr%3B%0A%20%20%20%20%7D%0Aprivate%3A%0A%20%20%20%20int%20destroyed%3B%0A%20%20%20%20std%3A%3Aweak_ptr%3CT%3E%20data%3B%0A%20%20%20%20AtomicLock%20destroyedLock%3B%0A%7D%0A%60%60%60%0A%E8%BF%99%E9%87%8C%E7%9A%84%E6%A0%B8%E5%BF%83%E6%80%9D%E6%83%B3%E6%98%AF%E7%94%A8%E8%87%AA%E5%AE%9A%E4%B9%89%E7%9A%84MyWeakPtr%E6%9B%BF%E4%BB%A3%E6%A0%87%E5%87%86%E5%BA%93%E7%9A%84weak_ptr%E3%80%82%E8%80%8C%E8%87%AA%E5%AE%9A%E4%B9%89%E7%9A%84MyWeakPtr%E9%99%A4%E4%BA%86std%3A%3Aweak_ptr%E5%A4%96%EF%BC%8C%E4%B8%8D%E5%86%8D%E5%90%AB%E6%9C%89%E4%BB%BB%E4%BD%95%E5%A0%86%E4%B8%8A%E5%88%86%E9%85%8D%E7%9A%84%E5%86%85%E5%AD%98%E3%80%82%E8%BF%99%E4%B9%9F%E4%BF%9D%E8%AF%81%E4%BA%86%E6%9E%90%E6%9E%84%E5%90%8E%E7%9A%84%E5%AE%89%E5%85%A8%E8%AE%BF%E9%97%AE%E3%80%82%E5%89%A9%E4%B8%8B%E7%9A%84%E5%B0%B1%E6%98%AF%E4%BF%9D%E8%AF%81%EF%BC%8Cweak_ptr%E6%9E%90%E6%9E%84%E5%90%8E%E4%B8%8D%E5%86%8D%E8%A2%AB%E8%AE%BF%E9%97%AE%E5%88%B0%E3%80%82%E6%80%9D%E8%B7%AF%E6%98%AF%E9%80%9A%E8%BF%87%E4%B8%80%E4%B8%AA%E5%8E%9F%E5%AD%90%E9%94%81%E6%9D%A5%E4%BF%9D%E6%8A%A4%E4%B8%80%E4%B8%AA%E6%9E%90%E6%9E%84%E7%9A%84%E6%A0%87%E5%BF%97%E4%BD%8D%E3%80%82%E7%A1%AE%E4%BF%9D%EF%BC%8C%E6%9E%90%E6%9E%84%E5%90%8E%EF%BC%8Cweak_ptr%E4%B8%8D%E5%86%8D%E8%A2%AB%E8%AE%BF%E9%97%AE%E3%80%82%0A**%E8%BF%99%E9%87%8C%E8%BF%98%E6%9C%89%E4%B8%80%E4%B8%AA%E9%9A%90%E8%94%BD%E7%9A%84%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E9%97%AE%E9%A2%98%E3%80%82**%0A-%20%E5%A6%82%E6%9E%9CMyWeakPtr%E9%A1%BA%E5%88%A9%E6%8B%BF%E5%88%B0line1%E8%BF%99%E4%B8%80%E8%A1%8C%E7%9A%84%E9%94%81%E3%80%82%E5%A6%82%E6%9E%9Cweak_ptr%E5%9C%A8line1-line2%E4%B9%8B%E9%97%B4%E8%BF%9B%E5%85%A5%E6%9E%90%E6%9E%84%EF%BC%8C%E7%94%B1%E4%BA%8E%E6%AD%A4%E6%97%B6%E6%9E%90%E6%9E%84%E8%A2%AB%E5%8E%9F%E5%AD%90%E9%94%81%E9%98%BB%E6%8C%A1%EF%BC%8C%E6%97%A0%E6%B3%95%E5%AE%8C%E6%88%90%EF%BC%8Cweak_ptr%E7%9A%84%E5%86%85%E5%AD%98%E5%9C%A8%E6%9E%90%E6%9E%84%E5%AE%8C%E6%88%90%E4%B9%8B%E5%89%8D%E6%98%AF%E4%B8%8D%E4%BC%9A%E8%A2%AB%E9%87%8A%E6%94%BE%E7%9A%84%E3%80%82%E6%89%80%E4%BB%A5line2%E5%8F%AF%E4%BB%A5%E5%9C%A8weak_ptr%E8%A2%AB%E6%9E%90%E6%9E%84%E5%89%8D%E5%AE%8C%E6%88%90%E8%B0%83%E7%94%A8%E3%80%82%E5%9B%A0%E4%B8%BAshared_ptr%E5%85%88%E4%BA%8Eweak_ptr%E6%9E%84%E9%80%A0%EF%BC%8C%E6%89%80%E4%BB%A5shared_ptr%E5%90%8E%E4%BA%8Eweak_ptr%E6%9E%90%E6%9E%84%E3%80%82%E6%89%80%E4%BB%A5%E6%AD%A4%E6%97%B6shared_ptr%E5%BF%85%E7%84%B6%E8%BF%98%E6%9C%89%E6%95%88%EF%BC%8C%E6%89%80%E4%BB%A5%E5%8F%AF%E4%BB%A5%E9%80%9A%E8%BF%87weak_ptr%E9%94%81%E4%BD%8Fshared_ptr%EF%BC%8C%E4%BD%BF%E5%85%B6%E4%B8%8D%E4%BC%9A%E8%A2%AB%E6%9E%90%E6%9E%84%E3%80%82%0A-%20%E5%90%8E%E7%BB%ADshared_ptr%E8%A2%AB%E6%9E%90%E6%9E%84%E5%90%8E%EF%BC%8C%E7%94%B1%E4%BA%8E%E6%9E%90%E6%9E%84%E9%A1%BA%E5%BA%8F%E7%9A%84%E5%85%B3%E7%B3%BB%EF%BC%8C%E6%AD%A4%E6%97%B6weak_ptr%E5%BF%85%E7%84%B6%E5%B7%B2%E5%AE%8C%E6%88%90%E6%9E%90%E6%9E%84%E5%87%BD%E6%95%B0%EF%BC%8C%E5%88%99%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E4%BC%9A%E9%80%89%E6%8B%A9destructor%3D%3D1%E7%9A%84%E5%88%86%E6%94%AF%EF%BC%8C%E8%80%8C%E4%B8%8D%E4%BC%9A%E6%89%A7%E8%A1%8Cweak_ptr.lock%E6%93%8D%E4%BD%9C%E3%80%82%0A%0A%E7%BB%BC%E4%B8%8A%E6%89%80%E8%BF%B0%EF%BC%8C%E6%9C%AC%E5%AE%9E%E7%8E%B0%E6%98%AF%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E7%9A%84%E3%80%82%0A%0A%E5%8F%A6%E5%A4%96%E4%B8%80%E7%82%B9%E5%80%BC%E5%BE%97%E6%B3%A8%E6%84%8F%E7%9A%84%E6%98%AF%EF%BC%8C%E8%BF%99%E9%87%8C%E5%B0%86GetInstance%E6%94%B9%E4%B8%BA%E8%BF%94%E5%9B%9E%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88%EF%BC%8C%E5%8D%B3%E5%8D%95%E4%BE%8B%E6%9E%90%E6%9E%84%E5%90%8E%E7%9A%84%E8%AE%BF%E9%97%AE%EF%BC%8C%E5%8F%AF%E8%83%BD%E8%BF%94%E5%9B%9Enullptr%EF%BC%8C%E4%BB%A5%E7%A4%BA%E5%AF%B9%E8%B1%A1%E5%B7%B2%E7%BB%8F%E4%B8%8D%E5%AD%98%E5%9C%A8%E4%BA%86%E3%80%82%E4%BD%86%E8%BF%99%E6%A0%B7%E7%9A%84%E8%AE%BE%E8%AE%A1%E5%8A%BF%E5%BF%85%E4%BC%9A%E5%BC%95%E8%B5%B7%E5%90%84%E5%A4%84nullptr%E7%9A%84%E5%88%A4%E6%96%AD%EF%BC%8C%E8%BF%99%E9%87%8C%E6%AF%94%E8%BE%83%E9%80%82%E5%90%88%E4%BD%BF%E7%94%A8Null%20Object%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E3%80%82%0A%0A%60%60%60c%2B%2B%0Aclass%20A%20%7B%0Apublic%3A%0A%20%20%20%20static%20std%3A%3Ashared_ptr%3CA%3E%20GetInstance()%20%7B%0A%20%20%20%20%20%20%20%20static%20std%3A%3Ashared_ptr%3CA%3E%20a%20%3D%20new%20A%3B%0A%20%20%20%20%20%20%20%20static%20MyWeakPtr%3CA%3E%20ref%20%3D%20a%3B%0A%20%20%20%20%20%20%20%20auto%20b%20%3D%20ref.Acquire()%3B%0A%20%20%20%20%20%20%20%20if%20(b%20%3D%3D%20nullptr)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20NullObjA%3A%3AGetInstance()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20b%3B%0A%20%20%20%20%7D%0A%7D%3B%0A%20%20%20%20...%0A%7D%3B%0A%0Aclass%20NullObjA%20%3A%20public%20A%20%7B%0Apublic%3A%0A%20%20%20%20void%20func()%20override%20%7B%7D%0A%20%20%20%20static%20GetInstance()%3B%0A%20%20%20%20%0Aprivate%3A%0A%20%20%20%20static%20NullObjA%20nullA%3B%0A%7D%0A%60%60%60%0A%E8%BF%99%E9%87%8CNullObjA%E4%B8%8D%E5%AD%98%E5%9C%A8%E6%9E%90%E6%9E%84%E9%97%AE%E9%A2%98%EF%BC%8C%E5%9B%A0%E4%B8%BA%E8%BF%99%E4%B8%AA%E5%AF%B9%E8%B1%A1%E9%87%8C%E5%8F%AA%E6%9C%89%E4%B8%80%E4%B8%AAvptr%EF%BC%8C%E5%95%A5%E9%83%BD%E6%B2%A1%E6%9C%89%EF%BC%8C%E8%80%8C%E8%BF%99%E4%B8%AA%E6%8C%87%E9%92%88%E6%98%AF%E9%9D%99%E6%80%81%E5%AF%B9%E8%B1%A1nullA%E7%9A%84%E9%99%84%E5%B1%9E%E7%89%A9%EF%BC%8C%E5%85%B6%E5%8D%A0%E6%9C%89%E7%9A%84%E5%86%85%E5%AD%98%E5%9C%A8nullA%E5%88%86%E9%85%8D%E7%9A%84%E6%97%B6%E5%80%99%E5%88%86%E9%85%8D%EF%BC%8C%E5%9C%A8nullA%E6%9E%84%E9%80%A0%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8C%E8%A2%AB%E8%B5%8B%E5%80%BC%E3%80%82%E8%80%8C%E4%B8%94nullA%E7%9A%84%E5%86%85%E5%AD%98%E6%98%AF%E9%9D%99%E6%80%81%E7%9A%84%E5%85%A8%E5%B1%80%E6%95%B0%E6%8D%AE%E5%8C%BA%EF%BC%8C%E6%98%AF%E4%B8%8D%E4%BC%9A%E8%A2%AB%E9%87%8A%E6%94%BE%E7%9A%84%E3%80%82%E6%89%80%E4%BB%A5%E5%AF%B9%E4%BB%96%E7%9A%84%E5%BC%95%E7%94%A8%E6%98%AF%E5%AE%89%E5%85%A8%E7%9A%84%E3%80%82%0A%E5%A5%BD%E4%BA%86%EF%BC%8C%E5%88%B0%E6%AD%A4%E7%AE%97%E6%98%AF%E6%8A%8A%E8%BF%99%E4%B8%AA%E9%97%AE%E9%A2%98%E8%A7%A3%E6%8E%89%E4%BA%86%EF%BC%8C%E5%AF%B9%E6%AF%94%E4%B8%80%E4%B8%8B%E4%BB%A3%E7%A0%81%EF%BC%8C%E7%9B%B8%E6%AF%94%E6%9C%80%E4%BC%98%E9%9B%85%E7%9A%84Meyer's%20Singleton%EF%BC%8C%E8%BF%99%E9%87%8C%E5%B7%B2%E7%BB%8F%E5%A4%9A%E5%87%BA%E5%BE%88%E5%A4%9A%E8%A1%8C%E4%BA%86%E3%80%82%0A%0A%23%20Take%20Aways%0A-%20%E5%A6%82%E6%9E%9C%E6%98%AF%E7%BA%AFC%2B%2B%E9%A1%B9%E7%9B%AE%EF%BC%8C%E8%AF%B7%E7%94%A8%E4%BE%9D%E8%B5%96%E5%85%B3%E7%B3%BB%E8%A7%A3%E5%86%B3%E6%9E%90%E6%9E%84%E9%97%AE%E9%A2%98%0A-%20%E5%A6%82%E6%9E%9C%E6%98%AFC%2FC%2B%2B%E6%B7%B7%E7%BC%96%E9%A1%B9%E7%9B%AE%EF%BC%8C%E8%AF%B7%E6%85%8E%E9%87%8D%E6%8F%90%E4%BE%9B%E5%85%A8%E5%B1%80%E5%AF%B9%E8%B1%A1%EF%BC%88%E5%8C%85%E6%8B%AC%E5%8D%95%E4%BE%8B%EF%BC%89%EF%BC%8C%E5%B0%A4%E5%85%B6%E6%98%AF%E5%A4%8D%E6%9D%82%E7%9A%84%E5%85%A8%E5%B1%80%E5%AF%B9%E8%B1%A1%E3%80%82%0A-%20%E5%A6%82%E6%9E%9C%E9%9D%9E%E6%8F%90%E4%BE%9B%E4%B8%8D%E5%8F%AF%EF%BC%8C%E8%AF%B7%E8%80%83%E8%99%91%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E5%92%8C%E6%9E%90%E6%9E%84%E5%AE%89%E5%85%A8%0A%0A%23%20%E5%8F%82%E8%80%83%E6%96%87%E7%8C%AE%0A%5B1%5D%20%5BC%2B%2B%20%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88%EF%BC%88shared_ptr%2Fweak_ptr%EF%BC%89%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%5D(https%3A%2F%2Fblog.csdn.net%2Fithiker%2Farticle%2Fdetails%2F51532484)%0A%5B2%5D%20shared_ptr%E6%BA%90%E7%A0%81%EF%BC%9A%5Bshared_ptr_base.h%5D(https%3A%2F%2Fcode.woboq.org%2Fgcc%2Flibstdc%2B%2B-v3%2Finclude%2Fbits%2Fshared_ptr_base.h.html)%2C%20%5Bshared_ptr.h%5D(https%3A%2F%2Fgcc.gnu.org%2Fonlinedocs%2Fgcc-4.6.0%2Flibstdc%2B%2B%2Fapi%2Fa01033_source.html)%0A%5B3%5D%20%5B%E5%BD%93%E6%9E%90%E6%9E%84%E5%87%BD%E6%95%B0%E9%81%87%E5%88%B0%E5%A4%9A%E7%BA%BF%E7%A8%8B%20%E2%94%80%E2%94%80%20C%2B%2B%20%E4%B8%AD%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E7%9A%84%E5%AF%B9%E8%B1%A1%E5%9B%9E%E8%B0%83%5D(https%3A%2F%2Fblog.csdn.net%2FSolstice%2Farticle%2Fdetails%2F5238671)%0A%0A