【问题标题】:How to define a template for pointers and dynamic memory allocation?如何为指针和动态内存分配定义模板?
【发布时间】:2012-09-07 21:23:16
【问题描述】:

我已经创建了一个名为 Queue 的类模板,但我在尝试使用指向另一个名为 Worker 的类作为类型的指针来实例化它时遇到问题。 Queue<Worker*>

我认为这个具体的 Queue 方法带来了问题:

// Add item to queue
template <typename Type>
bool Queue<Type>::enqueue(const Type& item)
{
    if (isfull())
        return false;
    Node* add = new Node; // create node
    // on failure, new throws std::bad_alloc exception
    add->item = item; // set node pointers (shallow copying!!!!!)
    add->next = nullptr;
    items++;
    if (front == nullptr) // if queue is empty,
        front = add; // place item at front
    else
        rear->next = add; // else place at rear
    rear = add; // have rear point to new node
    return true;
}

在类型参数是指针的情况下,我需要复制指向的值,而不是地址(我正在使用动态内存管理)以避免程序崩溃。

我不知道如何用模板解决这个问题。

有什么帮助吗?

【问题讨论】:

  • 大多数通用容器不知道它们持有指针,因此它们会进行浅拷贝
  • 如果您喜欢冒险,可以深入研究Boost Pointer Containers 的源代码,看看他们是如何做到的。

标签: c++ templates pointers dynamic-memory-allocation class-template


【解决方案1】:

使用特征技术。

我的意思是定义简单的结构,所有魔法都将在其中实现。像这样的 deep_copy:

  template <typename T>
  struct deep_copy {
     void do_copy(T& d, const T& s)
     {
        d = s;
     }
  };

指针的特化

   template <typename T>  
   struct deep_copy<T*> {
     void do_copy(T*& d, const T* s)
     {
       if(s) d=new(*s); else d=0; }};
     }
   };         

[UPDATE1] 更多详情和更多示例:

并在您的队列中使用 deep_copy:

template <typename T>
class Queue {
public:
   void push_back(const T& elem)
   {
       Node* n = new Node();
       copyTraits.doCopy(n->elem, elem);
   }
private:
  deep_copy<T> copyTraits;
};

或者甚至更好地将其设为模板的默认参数,例如 less 是地图的默认参数。

template <typename T, typename CopyTraits = deep_copy<T> >
class Queue {
public:
   void push_back(const T& elem)
   {
       Node* n = new Node();
       copyTraits.doCopy(n->elem, elem);
   }
private:
  CopyTraits copyTraits;
};

如果您希望Queue::~Qeueu() d-tor 安全,请不要忘记销毁方法:

  template <typename T>
  struct deep_copy {
     void do_copy(T& d, const T& s)
     {
        d = s;
     }
     void do_destroy(const T& elem) {} // do nothing
  };


   template <typename T>  
   struct deep_copy<T*> {
     void do_copy(T*& d, const T* s)
     {
       if(s) d=new(*s); else d=0; }};
     }
     void do_destroy(const T& elem) {
       delete elem;
     }
   };         


template <typename T, typename AllocTraits = deep_copy<T> >
class Queue {
public:
   ...
   ~Queue() {
      for (n in Nodes) { // pseudo-code
         allocTraits.doDestroy(n->elem);
      }
   }
private:
  AllocTraits allocTraits;
};

【讨论】:

  • 有趣...并且会节省大量代码重复。我得试试。谢谢!
  • 如果您可以编辑/格式化我的帖子,请。我从手机打字……无论如何,这种特征技术在模板世界中非常普遍。值得尝试和学习
  • 请注意我的更改。我不知道你是否使用过这个特性的东西 - 但是指针 doCopy 的声明应该引用目标指针(d):do_copy(T*&amp; d, const T* s)
【解决方案2】:

虽然它会导致一些代码重复,但您可以创建 Queue 类的特化,用于指针类型的实例化。为了减少代码重复量,我的建议是创建一个基类,每个专门的类都将从中继承,其中基类包含不会根据类的类型而改变的所有方法和成员实例化。

例如:

template<typename T>
base_queue; //keep everything "common" in this class

template<typename T>
queue : public base_queue<T> { ... }; //unspecialized queue class

template<typename T>
queue<T*> : public base_queue<T> { ... }; //pointer specialized version

现在在您的 Queue&lt;T*&gt; 类的专用版本中,您的 enqueue 方法可能如下所示:

template <typename T>
bool Queue<T*>::enqueue(const T* item)
{
    //... code

    add->item = *item; // copy the value being pointed to, not the pointer itself

    //... more code

    return true;
}

【讨论】:

    猜你喜欢
    • 2019-07-12
    • 2015-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-04
    • 1970-01-01
    • 2019-06-25
    • 1970-01-01
    相关资源
    最近更新 更多