SingleToN 与 auto_ptr

原创 2004年07月12日 14:31:00

SingleToN 即单件模式,意指:系统中某个类只有一个实例。这种情况是最多见的了,因此 SingleToN 也是运用最广泛的设计模式(因为诸多设计模式中,用得着它的地方太多了).但如 C++ 中
/*接口定义*/
class SingleToN
{
    public:
        static SingleToN* getInstance(void);

    private:
        static SingleToN*  g_instance;

    private:
        SingleToN();
};

/*实现*/
SingleToN* SingleToN::i_instance = NULL;

SingleToN::SingleToN()
{
}

SingleToN* SingleToN::getInstance(void)
{
    if ( g_instance == NULL )
    {
        g_instance = new SingleToN();
    }
   
    return g_instance;
}

/*然后可能这样引用该类:*/
int main(void)
{
    SingleToN* stn = SingleToN::getInstance();
    /*其它代码*/
    delete stn;
    return 0;
}
如上 main 方法中
delete stn;
所示:必须由 SingleToN 的引用者来释放 SingleToN::g_instance 的资源--这破坏了类 SingleToN 的独立性,可靠性也受到影响。于是你可能想这样修改上述代码:
/*接口定义*/
class SingleToN
{
    public:
        static auto_ptr<SingleToN>& getInstance(void);
        void method( void );
        ~SingleToN( void );

    private:
        static auto_ptr<SingleToN>  g_instance;

    private:
        SingleToN();
};

/*实现*/
auto_ptr<SingleToN> SingleToN::g_instance = auto_ptr<SingleToN>(0);

SingleToN::SingleToN()
{
    cout<<"ctor/n";
}

SingleToN::~SingleToN()
{
    cout<<"dtor/n";
}

auto_ptr<SingleToN>& SingleToN::getInstance(void)
{
    if ( g_instance.get() == 0 )
    {
        g_instance = auto_ptr<SingleToN>( new SingleToN() ) ;
    }
   
    return g_instance;
}

void SingleToN::method()
{
    cout<<"method was called./n";
}

然后可能这样引用该类:
int main(void)
{
    auto_ptr<SingleToN> stn = SingleToN::getInstance();
    /*其它代码*/
    /*delete stn;*/;
    return 0;
}

问题解决了?不一定。如果你采用的 C++ STL 之 auto_ptr,那么下面引用 SingleToN 的代码可能运行不正常:
typedef auto_ptr<SingleToN> stn_ptr;
void fun(void)
{
    cout<<"/nEntering fun......./n";
    stn_ptr stn = SingleToN::getInstance();
    stn->method();
    cout<<"Leaving fun ......./n/n";
}

void main( void )
{
    stn_ptr stn = SingleToN::getInstance();
    fun();                    
    stn->method();     
}
如上代码所示:在 C++ STL 中,main 作用域和 fun 作用域中的 stn 将不会代理一个相同的 SingleToN 实例,而会各自分别代理一个独立的 SingleToN ,这至少就破坏了“单件模式”,勿庸多言,这个影响是很坏的。
C++ STL 之 auto_ptr 产生上述错误的细节是这样的:
SingleToN::g_instance 因在赋值 main 域的 stn 变量时,它所代理的指针被 stn 剥夺(详见 auto_ptr 的赋值运算符重载方法。),所以,在向 fun 域的 stn 变量赋值时,SingleToN::g_instance 不得不生成一个新的 SingleToN 实例。

当 然,在所有引用 SingleToN 的地方都采用 auto_ptr<SingleToN>& 型变量而不用 auto_ptr<SingleToN> 型变量,可避免上述问题。但要保证这一点,如同要保证所有C/C++程序员都一定会正确释放指针资源。
    你可能四处寻找解决方案,但所有解决方案必然都围绕 SingleToN 类的实现或 auto_ptr 的实现。根据事发的原因,更多的焦点集中在 auto_ptr,这是问题产生的根源。microsoft vc++ 6 的 memory 头文件实现的 auto_ptr 方法避免了上述缺陷,但 VC7.x 中 auto_ptr  的实现完全引用自 C++ STL ,又“恢复了该缺陷"。
main 方法运行结果:
在 VC 6.x 中
ctor

Entering fun now....
metod was called
Leaving fun now....

dtor

在 VC7.x 中
ctor                                 给 main 域中 stn 变量赋值

Entering fun now....
ctor                                 给 fun 域中 stn 变量赋值
method was called
Leaving fun now....

dtor                                 析构 fun 域中 stn  所代理的指针的资源

method was called
dtor                                 析构 main 域中 stn  所代理的指针的资源

而如果将 main 方法中 stn 变量类型改为 auto_ptr<SingleToN>& 型,则在 VC7.x 下的表面更为奇怪,如下所示, SingleToN 唯一实例的析构已完毕,但它的 mothod 方法依然被调用运行:
ctor

Entering fun now....
method was called
Leaving fun now....

dtor

method was called                      // mothed 方法依然有效

浅谈auto_ptr智能指针

在c++标准库里主要有三个智能指针: ①auto_ptr 在任何情况下都不要使用 ②scoped_ptr 独占空间,防拷贝和赋值,是对第①个智能指针的缺陷所作出的解决 ③shared_ptr 利用...
  • qq_34992845
  • qq_34992845
  • 2017年04月02日 00:20
  • 822

实现auto_ptr的两种方法

我们都知道,实现auto_ptr有两种方法:第一种方法:在上一篇博客中我已经实现了,主要思想是管理权转移。第二种方法:它是我们c++标准库中以前的一个版本,主要思想是在auto_ptr类中除了有一个指...
  • xyzbaihaiping
  • xyzbaihaiping
  • 2016年04月11日 20:04
  • 1137

智能指针auto_ptr、内存泄漏解决

在C++11中,已经不使用auto_ptr,而用 unique_ptr进行替代,不过二者原理都差不多。头文件:memory智能指针:实质上是一个类,在创建智能指针的时候,本质上是在栈上创建了一个对象...
  • wang664626482
  • wang664626482
  • 2016年08月29日 20:02
  • 736

智能指针auto_ptr详解

1. 智能指针auto_ptr的引入 auto_ptr是C++标准库中的智能指针模板类,头文件 auto_ptr的出现,主要是为了解决“有异常抛出时发生内存泄漏”的问题。如下的简单代码是这类问题的...
  • u010984552
  • u010984552
  • 2016年10月25日 09:08
  • 614

auto_ptr 与 shared_ptr 用法和区别总结

1.auto_ptr 被复制后,将失去原来所致资源的所有权;
  • Manketon
  • Manketon
  • 2014年07月08日 12:29
  • 2000

std::auto_ptr的原理及使用

使用auto_ptr作为成员变量,以避免资源泄漏。防止资源泄漏,我们通常在构造函数中申请,析构函数中释放,但是只有构造函数调用成功,析构函数才会被调用,换句话说,如果在构造函数中产生了异常,那么析构函...
  • makenothing
  • makenothing
  • 2015年11月13日 17:38
  • 3667

C++智能指针auto_ptr详解

auto_ptrauto_ptr是C++标准库中()为了解决资源泄漏的问题提供的一个智能指针类模板(注意:这只是一种简单的智能指针)auto_ptr的实现原理其实就是RAII,在构造的时候获取资源,在...
  • gatieme
  • gatieme
  • 2016年03月20日 23:37
  • 2406

C++标准库智能指针(std::auto_ptr)

智能指针两大特性: 1.构造栈对象的生命期控制堆上构造的对象的生命期 2.通过release来保证auto_ptr对对象的独权. 另必须使用显示构造 文章结构: 一、剖析C++标准库智能指针...
  • cbNotes
  • cbNotes
  • 2014年08月29日 15:31
  • 2021

我所熟悉的C++智能指针auto_ptr vs shared_ptr (一)

在开发过程中,曾经使用过两种C++的智能指针,如今,便总结一下,顺便比较比较二者使用中的区别,注意避免入坑的危险。:-D 我们知道,在C++中,如果创建一个指向某个对象的指针,那么在使用完这个对象...
  • u013700658
  • u013700658
  • 2015年10月28日 09:24
  • 1460

C++中多线程与Singleton的那些事儿

前言 前段时间在网上看到了个的面试题,大概意思是如何在不使用锁和C++11的情况下,用C++实现线程安全的Singleton。 看到这个题目后,第一个想法就是用Scott Meyer在《Effec...
  • zmlcool
  • zmlcool
  • 2016年06月11日 17:56
  • 773
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:SingleToN 与 auto_ptr
举报原因:
原因补充:

(最多只允许输入30个字)