Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.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++;指针树模板问题_C++_Templates_Memory Management_Tree - Fatal编程技术网

C++ C++;指针树模板问题

C++ C++;指针树模板问题,c++,templates,memory-management,tree,C++,Templates,Memory Management,Tree,我刚刚遇到了一个由Kasper Peeters编写的类似STL的树容器类: 然而,因为它类似于STL,所以它倾向于在树中使用单个类类型;i、 e.模板。与STL列表一样,如果它遇到多态类问题,问题在于树中的对象是指向基于堆的对象的指针(如指向基类的指针),在删除节点时不会被销毁 因此,我的选择是: 1:使用boost::shared_ptr树,尽管这比我想要的更昂贵/更过分 2:写一个像我在下面写的那样的指针包装器。其思想是它包装一个指针,当指针超出范围时,它会删除指针。它不是ref计数的,它

我刚刚遇到了一个由Kasper Peeters编写的类似STL的树容器类:

然而,因为它类似于STL,所以它倾向于在树中使用单个类类型;i、 e.
模板
。与STL列表一样,如果它遇到多态类问题,问题在于树中的对象是指向基于堆的对象的指针(如指向基类的指针),在删除节点时不会被销毁

因此,我的选择是:

1:使用boost::shared_ptr树,尽管这比我想要的更昂贵/更过分

2:写一个像我在下面写的那样的指针包装器。其思想是它包装一个指针,当指针超出范围时,它会删除指针。它不是ref计数的,它只是保证了指针的破坏

template<class T>
class TWSafeDeletePtr
{
private:
    T *_ptr;
public:
    TWSafeDeletePtr() : _ptr(NULL) {}
    TWSafeDeletePtr(T *ptr) : _ptr(ptr) {}
    ~TWSafeDeletePtr()
    { 
        delete _ptr;
    }
    T &operator=(T *ptr)
    {
        assert(!_ptr);
        delete _ptr;
        _ptr=ptr;
        return *ptr;
    }
    void set(T *ptr)
    {
        *this=ptr;
    }

    T &operator*() const { return *_ptr; }
    T *operator->() const { return _ptr; }
};
模板
类TWSafeDeletePtr
{
私人:
T*_ptr;
公众:
TWSafeDeletePtr():ptr(NULL){}
TWSafeDeletePtr(T*ptr):_ptr(ptr){}
~TWSafeDeletePtr()
{ 
删除(ptr);;
}
T&运算符=(T*ptr)
{
断言(!\u ptr);
删除(ptr);;
_ptr=ptr;
返回*ptr;
}
无效集(T*ptr)
{
*这=ptr;
}
T&运算符*()常量{return*ptr;}
T*运算符->()常量{return_ptr;}
};
3:编写我自己的分配器,它在allocate()中从池中分配节点对象,并在deallocate()中删除指向内存的对象

4:专门编写代码以生成指针树,避免初始分配和复制构造,并天生知道如何删除指向的数据

我已经有了选项2,但我对它不是很满意,因为我必须先插入一个空的ptr,然后在插入返回迭代器时设置()指针。这是因为树使用复制构造,因此在堆栈上传递的临时对象将在指针超出范围时最终删除指针。所以我在返回时设置了指针。它是有效的,它是隐藏的,但我不喜欢它

选项3看起来是最好的候选人,但是我想我会问是否有其他人已经这样做了,或者有任何其他建议

好的,我决定使用选项1(共享目录树),主要是因为它使用标准库,但也因为每个节点额外的引用计数不会破坏库。谢谢大家的回复:)

干杯


Shane

我不喜欢分配器版本,因为分配器应该分配内存,而不是构造对象。因此,无法保证向分配器请求的分配数量与要构造的对象数量相匹配;这将取决于你能否顺利实施

在分配器为其分配内存后,该树对插入值或附加值调用复制构造函数,因此您将很难编写能够处理多态对象的内容-alloc_3;。在调用构造函数之前,allocate不知道x的运行时类型(第886行):

再看看代码,它似乎根本不使用赋值,而且包装器只提供默认的复制构造函数,所以我看不到任何建议的机制在工作——当节点被赋值为与它已经拥有的值相同的值时,这段代码称为(第1000行):

模板
模板
iter树::替换(iter位置,常数T&x)
{
kp::析构函数(&position.node->data);
kp::构造函数(&position.node->data,x);
返回位置;
}
在这里调用它们的析构函数时,您的智能指针将析构函数它们的引用对象;您可以通过传递一个引用计数的指针来避免它(因此,在它超出范围之前,x不会销毁它的引用,而不是position.node->data析构函数销毁它)


如果您想使用此树,那么我将使用它作为其他地方拥有的数据的索引,而不是拥有数据的树,或者坚持使用共享的方法。

首先,您可以从这里的移动语义中获益。如果您有权访问C++0x

另外,Boost指针容器库通过以下方式解决了指针STL容器的问题。。。重新编码

您没有提到的指针容器的另一个问题是容器的副本。在您的情况下,原始容器及其副本都指向相同的对象,因此更改其中一个对象不会更改另一个对象

当然,您可以通过编写一个代理类来缓解这一问题,该类封装指针并提供深度复制语义(
clone
对象封装中的方法)。但是如果容器是指针感知的,那么您将更频繁地复制数据。。。。不过工作要少一些

/// Requirement: T is a model of Cloneable
template <class T>
class Proxy
{
  template <class> friend class Proxy;
public:
  // Constructor
  Proxy(): mPointer(0) {}
  explicit Proxy(T* t): mPointer(t) {}
  template <class U>
  explicit Proxy(std::auto_ptr<U> t): mPointer(t.release()) {}
  template <class U>
  explicit Proxy(std::unique_ptr<U> t): mPointer(t.release()) {}

  // Copy Constructor
  Proxy(Proxy const& rhs):
    mPointer(rhs.mPointer ? rhs.mPointer->clone() : 0) {}
  template <class U>
  Proxy(Proxy<U> const& rhs):
    mPointer(rhs.mPointer ? rhs.mPointer->clone() : 0) {}

  // Assignment Operator
  Proxy& operator=(Proxy const& rhs)
  {
    Proxy tmp(rhs);
    this->swap(tmp);
    return *this;
  }
  template <class U>
  Proxy& operator=(Proxy<U> const& rhs)
  {
    Proxy tmp(rhs);
    this->swap(tmp);
    return *this;
  }

  // Move Constructor
  Proxy(Proxy&& rhs): mPointer(rhs.release()) {}
  template <class U>
  Proxy(Proxy<U>&& rhs): mPointer(rhs.release()) {}

  // Move assignment
  Proxy& operator=(Proxy&& rhs)
  {
    Proxy tmp(rhs);
    this->swap(tmp);
    return *this;
  }
  template <class U>
  Proxy& operator=(Proxy&& rhs)
  {
    Proxy tmp(rhs);
    this->swap(tmp);
    return *this;
  }

  // Destructor
  ~Proxy() { delete mPointer; }

  void swap(Proxy& rhs)
  {
    T* tmp = rhs.mPointer;
    rhs.mPointer = mPointer;
    mPointer = tmp;
  }

  T& operator*() { return *mPointer; }
  T const& operator*() const { return *mPointer; }

  T* operator->() { return mPointer; }
  T const* operator->() const { return mPointer; }

  T* release() { T* tmp = mPointer; mPointer = 0; return tmp; }

private:
  T* mPointer;
};

// Free functions
template <class T>
void swap(Proxy<T>& lhs, Proxy<T>& rhs) { lhs.swap(rhs); }
///需求:T是可克隆的模型
模板
类代理
{
模板好友类代理;
公众:
//建造师
Proxy():mPointer(0){}
显式代理(T*T):mPointer(T){}
模板
显式代理(std::auto_ptr t):mPointer(t.release()){}
模板
显式代理(std::unique_ptr t):mPointer(t.release()){
//复制构造函数
代理(代理常量和rhs):
mPointer(rhs.mPointer?rhs.mPointer->clone():0){}
模板
代理(代理常量和rhs):
mPointer(rhs.mPointer?rhs.mPointer->clone():0){}
//赋值运算符
代理和运算符=(代理常量和rhs)
{
代理tmp(rhs);
本->交换(tmp);
归还*这个;
}
模板
代理和运算符=(代理常量和rhs)
{
代理tmp(rhs);
本->交换(tmp);
归还*这个;
}
//移动构造函数
代理(Proxy&&rhs):mPointer(rhs.release()){}
模板
代理(Proxy&&rhs):mPointer(rhs.release()){}
//移动分配
代理和运算符=(代理和rhs)
{
代理tmp(rhs);
本->交换(tmp);
归还*这个;
}
模板
代理和运算符=(代理和rhs)
{
代理tmp(rhs);
本->交换(tmp);
归还*这个;
}
template <class T, class tree_node_allocator>
template <class iter>
iter tree<T, tree_node_allocator>::replace(iter position, const T& x)
    {
    kp::destructor(&position.node->data);
    kp::constructor(&position.node->data, x);
    return position;
    }
/// Requirement: T is a model of Cloneable
template <class T>
class Proxy
{
  template <class> friend class Proxy;
public:
  // Constructor
  Proxy(): mPointer(0) {}
  explicit Proxy(T* t): mPointer(t) {}
  template <class U>
  explicit Proxy(std::auto_ptr<U> t): mPointer(t.release()) {}
  template <class U>
  explicit Proxy(std::unique_ptr<U> t): mPointer(t.release()) {}

  // Copy Constructor
  Proxy(Proxy const& rhs):
    mPointer(rhs.mPointer ? rhs.mPointer->clone() : 0) {}
  template <class U>
  Proxy(Proxy<U> const& rhs):
    mPointer(rhs.mPointer ? rhs.mPointer->clone() : 0) {}

  // Assignment Operator
  Proxy& operator=(Proxy const& rhs)
  {
    Proxy tmp(rhs);
    this->swap(tmp);
    return *this;
  }
  template <class U>
  Proxy& operator=(Proxy<U> const& rhs)
  {
    Proxy tmp(rhs);
    this->swap(tmp);
    return *this;
  }

  // Move Constructor
  Proxy(Proxy&& rhs): mPointer(rhs.release()) {}
  template <class U>
  Proxy(Proxy<U>&& rhs): mPointer(rhs.release()) {}

  // Move assignment
  Proxy& operator=(Proxy&& rhs)
  {
    Proxy tmp(rhs);
    this->swap(tmp);
    return *this;
  }
  template <class U>
  Proxy& operator=(Proxy&& rhs)
  {
    Proxy tmp(rhs);
    this->swap(tmp);
    return *this;
  }

  // Destructor
  ~Proxy() { delete mPointer; }

  void swap(Proxy& rhs)
  {
    T* tmp = rhs.mPointer;
    rhs.mPointer = mPointer;
    mPointer = tmp;
  }

  T& operator*() { return *mPointer; }
  T const& operator*() const { return *mPointer; }

  T* operator->() { return mPointer; }
  T const* operator->() const { return mPointer; }

  T* release() { T* tmp = mPointer; mPointer = 0; return tmp; }

private:
  T* mPointer;
};

// Free functions
template <class T>
void swap(Proxy<T>& lhs, Proxy<T>& rhs) { lhs.swap(rhs); }
map<int, ExpensiveElement> my_map;

// default constructs ExpensiveElement 
// and calls ExpensiveElement::do_something().
// No copies of ExpensiveElement are made!
my_map[7].do_something();
map<int, ExpensiveElement> my_map;

// construct an ExpensiveElement and swap it into the map
// this avoids redundant work and copying and can be very 
// efficient if the default constructor of ExpensiveElement
// is cheap to call
ExpensiveElement element(...);
my_map[7].swap(element);