繁体   English   中英

我要正确删除我的结构吗?

[英]Am I Deleting my struct Properly?

这是一项家庭作业。 Field容器是一周前的任务,现在我应该使用Field容器作为结构NumPair的动态数组,该结构包含两个char *如下所示:

struct NumPair
{
 char *pFirst, *pSecond;
 int count;

 NumPair( char *pfirst = "", char *psecond = "", int count = 0)
  : pFirst(strdup(pfirst)), pSecond(strdup(psecond)), count(count)
 { }

NumPair( const NumPair& np )
    : count(np.count), pFirst(strdup(np.pFirst)), pSecond(strdup(np.pSecond))
{   }

NumPair& operator=( const NumPair& np )
{
    if(this != &np)
    {
        pFirst  = strdup(np.pFirst);
        pSecond = strdup(np.pSecond);
        count = np.count;
    }

    return *this;
}

和Field容器

Field<NumPair> dict_;

作业需要使用char * ,而不是string,以便我们可以使用所有这些低级的东西变得更好。 我已经有一些关于char到wchar_t转换的问题,等等。

现在我有一个问题要问我是否正在正确破坏NumPair。 场景如下:

1)现场析构函数被调用

template <class T>
Field<T>::~Field()
{
 delete[] v_;
}

2)删除v_中每个元素NumPair的析构函数;

~NumPair()
{
 free(pFirst);
 free(pSecond);
}

这个可以吗? 我还没有真正阅读太多关于混合和匹配在堆和免费存储上创建的元素的文章。 我认为只要不对不适当的malloc元素使用delete,我就可以了。

但是,我不知道delete命令的全部复杂性,所以我想知道这是否是有效的设计,以及如何做才能使它更好。

另外,当然不是。 我收到以下类型的错误:

This may be due to a corruption of the heap并指向dbgheap

extern "C" _CRTIMP int __cdecl _CrtIsValidHeapPointer(
  const void * pUserData
  )
{
  if (!pUserData)
   return FALSE;

  if (!_CrtIsValidPointer(pHdr(pUserData), sizeof(_CrtMemBlockHeader), FALSE))
   return FALSE;

  return HeapValidate( _crtheap, 0, pHdr(pUserData) ); // Here
}

同样,我如何在不使用字符串的情况下改善此问题?

FIELD CTOR /复制Ctor /任务

template <class T>
Field<T>::Field()
    : v_(0), vused_(0), vsize_(0)
{ }

template <class T>
Field<T>::Field(size_t n, const T &val)
    : v_(0), vused_(n), vsize_(0)
{
    if(n > 0)
    {
        vsize_ = 1;
        while(vsize_ < n)
            vsize_ <<= 1;

        v_     = new T[vsize_];
        std::fill(v_, (v_ + vused_), val);
    }
}

template <class T>
Field<T>::Field(const Field<T> &other)
    : v_(new T[other.vsize_]), vsize_(other.vsize_), vused_(other.vused_)
{ 
    std::copy(other.v_, (other.v_ + other.vused_), v_);
}

template <class T>
Field<T>& Field<T>::operator =(const Field<T> &other)
{
    this->v_     = other.v_;
    this->vused_ = other.vused_;
    this->vsize_ = other.vsize_;

    return *this;
}

现场成员

T *v_;
size_t vsize_;
size_t vused_;

您在NumPair中进行的字符串处理看起来还可以(strdup + free),并且您的Field容器delete []看起来还可以,但是很难说,因为您没有显示v_是什么。

eq在评论中提到您还应该提防如何复制NumPairs。 默认情况下,C ++将为您提供一个隐式的成员式副本构造函数。 在这里,像std :: string这样的RAII类型可以使您的生活更轻松:可以复制包含std :: string的struct,而无需您进行任何特殊处理,并且字符串的副本将照顾字符串中引用的内存。 如果您复制NumPair(例如,通过分配它或从一个函数返回它),则临时目录的销毁将使您的字符串从下面释放出来。

您的Field复制构造函数仅复制v_中的指针。 如果您有一个字段的两个副本,则当第一个字段超出范围时,将删除v_中的所有NumPair,然后在第二个字段超出范围时再次删除。

您的复制构造函数(Field <>的)看起来不错,但是operator=有问题。

它不仅会泄漏内存(原始v_ ?会发生什么情况),而且此后,Field <>的两个实例持有一个指向同一内存块的指针,而第一个被破坏的实例将使其他v_无效。您甚至无法判断这是否发生了。

决定如何处理operator=并不总是那么容易-有些人认为隐式move语义还可以,但是我们其余的人则可以通过std::auto_ptr看到大多数人如何使用它。 可能最简单的解决方案是完全禁用复制,并使用显式函数来移动所有权。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM