Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 模板成员函数、静态局部变量和销毁顺序_C++_Templates_Memory Management_C++11_Static - Fatal编程技术网

C++ 模板成员函数、静态局部变量和销毁顺序

C++ 模板成员函数、静态局部变量和销毁顺序,c++,templates,memory-management,c++11,static,C++,Templates,Memory Management,C++11,Static,首先,为我的英语感到抱歉: 我设计了一个小库来管理我的程序使用的内存。它主要实现一种具有内存管理目的的共享对象。我有以下类(我省略了在这里不需要解释我的问题的其他成员和函数): 一种称为数据包的参数化结构,包含类型为T的子对象和计数器: 一个名为pool的类,带有一个静态参数函数(当然还有其他代码),返回对ptrstack的引用: 用户类继承共享对象: struct internals\u t;//.cpp源代码中的定义(pImpl习惯用法)。 //`shared_obj`只使用指向

首先,为我的英语感到抱歉:

我设计了一个小库来管理我的程序使用的内存。它主要实现一种具有内存管理目的的共享对象。我有以下类(我省略了在这里不需要解释我的问题的其他成员和函数):

  • 一种称为
    数据包
    的参数化结构,包含类型为
    T
    的子对象和计数器:
  • 一个名为
    pool
    的类,带有一个静态参数函数(当然还有其他代码),返回对
    ptrstack
    的引用:
  • 用户类继承共享对象:
struct internals\u t;//.cpp源代码中的定义(pImpl习惯用法)。
//`shared_obj`只使用指向其类型参数的指针。
类用户:公共共享对象
{
//成员函数访问其内部指针。
//'user_t'非常轻。它只包含一个指针,但可以用作
//普通物体。
//此外,我可以使用动态对象,而无需使用“新建”和“删除”
//因为内存是由shared_obj管理的
};
施工、分配/复制和销毁基本上执行以下操作:

  • 每次要创建新的
    共享对象时,都会在堆中创建一个
    数据包*
  • 每次复制
    共享对象时,其相关数据包的计数器都会递增
  • 每次调用
    共享对象的析构函数时,其相关数据包的计数器都会递减
  • 如果其关联数据包的计数器达到0,则通过以下方式将其关联指针推送到堆栈上:
pool::get().push(ptr);
  • 因此,我重新定义了这个列表的第一点:当需要创建一个新的
    数据包*
    ,并且其类型的池为空时,将在堆中创建一个新数据包。如果池不是空的,我使用“就地”版本的新:
new(pool::get().top())T(args);
pool::get().pop();
因此,当程序退出时,销毁被委派,所有创建的内存都可以重用

解释够了

我的问题是:我需要类型为“
user\t
”的任何其他静态对象(实际上,不同类型的不同对象继承了
shared\u obj
),但它们中的任何一个都会产生内存泄漏,我认为原因如下:

  • 静态对象是在创建其关联池之前创建的,因为每个类型的
    packet\u pool.get()
    的定义都是在定义之后实例化的:模板定义在使用的第一个指针中实例化为具体类型,而不是在编写模板的位置。因此,我的文件中的词法顺序与翻译单元中的定义顺序不同
  • 因此,我的静态对象在其关联池之后被销毁,因为静态对象的删除顺序与其构造顺序相反,这与其转换单元的定义顺序一致
  • 当静态对象被销毁时,其关联的计数器达到0,并且它们试图被推入其已销毁的池中。这就造成了崩溃
我最后的疑问是:

  • 翻译单元中实例化模板函数的具体“定义顺序”是什么?我的假设正确吗
这里有一个平行的问题:

  • 问题是否也与池是本地静态函数或“get”函数本身是内联函数(因为它是在其类中定义的函数)有关?我的意思是,每个“池”(每个堆栈)是否有内部链接,对于不同的翻译单元中的相同类型,是否有不同的

我觉得所有这些都可以简化为一个10行代码片段,一个非常简短的问题…“parametric”是一个错误的词。你是说“模板”。
template<class T>
struct packet
{
   T t;
   unsigned counter;
};
template<typename T>
struct ptrstack : public std::stack<T*>
{
  ~ptrstack()
  {
      while(!this->empty()) {
        delete this->top();
        this->pop();
      }
  }
};
class pool
{
   template<class T>
   using stack_tp = ptrstack<packet<T> >;

public:
   template<class T>
   static stack_tp<T>& get()
   {
     static stack_tp<T> pool;

     return pool;
   }
};
template<typename T>
class shared_obj
{ /* Members (see below) */ };
struct internals_t; // definition in a .cpp source code (pImpl idiom).

// `shared_obj` uses only pointer to its type parameter.
class user_t : public shared_obj<internals_t>
{
  // member functions accessing its internal pointer. 
  // `user_t` is very light. It only mantains a pointer, but it could be used as
  // a common object.
  // moreover, I can work with dynamic objects without using new and delete
  // since the memory is managed by shared_obj
};
pool::get<T>().push(ptr);
new (pool::get<T>().top()) T(args);
pool::get<T>().pop();