如何保证一个对象最先构造,最后析构?

2009-11-17
这是我在百度知道上的问题:
    程序中有一个对象是其它对象必需依赖的,如何保证这个被依赖的对象在所有依赖它的对象构造之前构造,析构之后析构后呢,C++语言好像没有强制规定全局对象的构造与析构顺序,求不依赖特定实现平台的解决方案,肯请大师们多多赐教!

以下是热心人的回答:
不用可以去关注。
如果它是对象是全局的,那么反正不析构。如果是局部的,那么其他跟他相关的对象也是局部的,那么在析构时,他们会自动优先被析构。如果相关对象为全局的,那么是你的数据结构有问题,要重新架构
回答者:  曹糯糯 - 举人 四级   2009-11-17 00:43
  
我不太明白你的意思,这看上去像个非常简单的问题.
把对象定义为全局.
编译器先为全局对象分配内存空间.然后主线程进入main()或者WinMain()函数开始执行.
#include<iostream>
Class A ;
Class B ;
int main()
{
Class C ;
}
B 和 C都可以很安全的使用A 作为它的成员.
回答者: jackheroes8383 - 助理 四级   2009-11-17 01:00

看来你的题有个问题没有搞懂,就是什么叫做“有一个对象是其他对象必需依赖的 ”
说清楚这里估计能够解决
回答者: keepingdo - 中级弟子 二级   2009-11-17 01:01

使用一个类做全局变量,它只管构造和析构其他的类的实例。
用全局指针来管理。
class A{...};
clase B{...};
clase C{...};
A * a1;
B * b1;
C * c1;
class Manage {
public:
Manage(){
a1 = new A();
b1 = new B();
c1 = new C();
}
virtual ~Manage()
{
delete c1;
delete b1;
delete a1;
}
};
Manage g_manage;
可以保证 a1 在 b1 之前构造,之后析构。
如果指针用的不爽,可以用引用
A & aa1 = *a1;
g_manage是全局变量,所以程序启动时构造,
结束时析构。不信可以加断点跟踪。
回答者: Laplas - 江湖豪侠 九级   2009-11-17 01:34

其实不用关注,编译时会查出错误。
你愿意,可以用宏
#ifndef CLASS_BAS   //如果没有声明 Class BAS
Class BAS;  
#define CLASS_BAS  
#endif
#ifdef CLASS_BAS //如果 声明 了 Class BAS
CLASS C;  // 则声明C;
CLASS D;  // 则声明D;
#endif
可以用宏描述  C 已deleted, D 已deleted
#ifndef C_deleted
delete C
#define C_deleted
#endif
#ifndef D_deleted
delete D
#define D_deleted
#endif
#ifdef C_deleted
#ifdef D_deleted
delete BAS
#endif
#endif
回答者:  L_o_o_n_i_e - 首席运营官 十五级   2009-11-17 05:56

在同一编译单元里, 最先定义的全局对象最先构造, 最后析构, 这是确定的
问题是不同编译单元之间的对象构造和析构顺序是不确定的
如果这个顺序真的很重要的话(实际上我很怀疑。。) , 你可以吧所有全局对象在同一个.cpp中定义, 在其它文件里只用 extern
回答者: vbtraz - 下位魔导师 十一级   2009-11-17 09:32

以下是我回复:
很感谢大家的热心帮助,不过你们的回答都不太理想,分述如下:
to曹糯糯:如果是一个库的初始化呢?不能不关注吧!
to jackheroes8383:因为C++标准没有强制规定全局对象的构造顺序,所以你的方法不把稳。
to keepingdo:就是初始化只需要一次,并且是在程序开始的时侯初始化,程序的最后析构,所以一般把它们定义为全局变量,并且类中用一个静态成员保证其初始化过程只进行一次,但问题是,必须保证它的初始化在那些依赖它的对象构造之前,它的析构在那些依赖它的对象析构之后,你不能限定这些对象不能定义为全局的,因为这个类不是只提供你个人使用,而C++又没强制规定了全局对象的构造和析构顺序,通常都是按照声明的顺序进行构造,相反的顺序析构,但不保证不会出现例外情况。
to Laplas: 你的方法倒是可以,但问题是我现在不知道那些类的定义,等我知道了,我的代码已经木已成舟,所以你的方法也行不通。
to L_o_o_n_i_e:你的方法不太理解。
to vbtraz: 问题就是我不是这个类的使用者,而我也不想给客户太多限制,那会让人很不爽。

以下是我的解决:
最后大家来看看我的解决方案,评一下优缺点吧!点评好的我会再加分的。
//支持者
class CSupporter
{
public:
  CSupporter(){if(NULL==m_pUS)m_pUS=new UserSupporter;}
  ~CSupporter()
  {
   if(NULL!=m_pUS&&0==--m_pUS->m_UserCount)
   {
    delete m_pUS;
    m_pUS=NULL;
   }
  }
  CSupporter(const CSupporter& src){if(NULL!=m_pUS)++m_pUS->m_UserCount;}
  CSupporter& operator=(const CSupporter& src){return *this;}
private:
  struct UserSupporter
  {
   long m_UserCount;
   UserSupporter():m_UserCount(1){cout<<"构造支持者"<<(unsigned long)this<<"!"<<endl;}
   ~UserSupporter(){cout<<"析构支持者"<<(unsigned long)this<<"!"<<endl;}
  };
  static UserSupporter* m_pUS;
};
CSupporter::UserSupporter* CSupporter::m_pUS=NULL;

//用户类
class CA
{
public:
  CA(const CSupporter& Supporter):m_Supporter(Supporter)
    {cout<<"构造CA对象"<<(unsigned long)this<<"!"<<endl;}
  ~CA(){cout<<"析构CA对象"<<(unsigned long)this<<"!"<<endl;}
private:
  CSupporter m_Supporter;
};
class CB
{
public:
  CB(const CSupporter& Supporter):m_Supporter(Supporter)
    {cout<<"构造CB对象"<<(unsigned long)this<<"!"<<endl;}
  ~CB(){cout<<"析构CB对象"<<(unsigned long)this<<"!"<<endl;}
private:
  CSupporter m_Supporter;
};
class CC
{
public:
  CC(const CSupporter& Supporter):m_Supporter(Supporter)
    {cout<<"构造CC对象"<<(unsigned long)this<<"!"<<endl;}
  ~CC(){cout<<"析构CC对象"<<(unsigned long)this<<"!"<<endl;}
private:
  CSupporter m_Supporter;
};
class CD
{
public:
  CD(const CSupporter& Supporter):m_Supporter(Supporter)
    {cout<<"构造CD对象"<<(unsigned long)this<<"!"<<endl;}
  ~CD(){cout<<"析构CD对象"<<(unsigned long)this<<"!"<<endl;}
private:
  CSupporter m_Supporter;
};

int main()
{  
//为了使输出都能看得见,测试我放在了main()函数内。
CSupporter supporter1, supporter2;
CA a1(supporter1), a2(supporter2);
CB b1(supporter1), b2(supporter2);
CD d1(supporter1), d2(supporter2);
CC c1(supporter1), c2(supporter2);
a1=a2;
c2=c1;
return 0;
}

主要思想:通过引用计数保证CSupporter对象在其它所有依赖它的对象析构之后析构,通过静态成员保证唯一实例,并且只初始化一次,通过限制用户类的构造函数参数里必须有一个CSupporter类型的参数,保证了在构造用户类对象之前必须先有一个CSupporter实例存在。

结果:
构造支持者11468864!
构造CA对象1244984!
构造CA对象1244980!
构造CB对象1244976!
构造CB对象1244972!
构造CD对象1244968!
构造CD对象1244964!
构造CC对象1244960!
构造CC对象1244956!
析构CC对象1244956!
析构CC对象1244960!
析构CD对象1244964!
析构CD对象1244968!
析构CB对象1244972!
析构CB对象1244976!
析构CA对象1244980!
析构CA对象1244984!
析构支持者11468864!
Press any key to continue
最新评论
暂无评论
参与评论

商务合作 查看更多

编辑推荐 查看更多
【爆款新游】【潜力佳作】分析系列
推广