CSDN博客

img _17708668

SingleToN 与 auto_ptr

发表于2004/7/12 14:31:00  752人阅读

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 方法依然有效
0 0

相关博文

我的热门文章

img
取 消
img