2012-01-29 80 views
2

这是我无法理解。 比方说,我重载operator &制造和和两个对象,和运营商之间=进行分配(使对象的副本)。 让我们假设我有一个命名为A类,而这个代码:运营商超载:内存泄漏

A a1,a2,a3; 
// initialize a1,a2,a3 
a1=a2&a3; 

如果A1已经分配的,当我A1分配对a2 & A3,有内存泄漏? 是在不删除旧对象的情况下创建的新对象?

PS:运营商使用A型的两个参数,重载(我还没有定义的类A,这是一个例子),返回类型A的参数,被定义为类的朋友。

代码:

这是一个很长的代码,所以我用引擎收录: http://pastebin.com/42TnThfC 但因为它是很长,我也张贴了最有意义的部分:

template<class T> 
List<T>& List<T>::operator= (List<T>& l) 
{ 
    List<T>* ptr=l.next; 
    if(this!=&l) 
    { 
     resize(0); 
     while(!ptr->end) 
     { 
      push(ptr->info); 
      ptr=ptr->next; 
     } 
    } 
    return *this; 
} 

template <class T> 
List<T>& operator& (List<T>& l1, List<T>& l2) throw() 
{ 
    List<T>* temp,*ptr=l1.next; 
    temp=new List<T>(); 
    try 
    { 
     if((l1.end)^(l2.end)) 
      throw excp1; 
    } 
    catch (char *s) 
    { 
     cout << "Exception: "<<s<<endl; 
    } 
    if(l1.end) 
    { 
     while(!ptr->end) 
     { 
      if(l2.in(ptr->info)) 
       temp->push(ptr->info); 
      ptr=ptr->next; 
     } 
    } 
    else 
    { 
     if(l1.info==l2.info) 
      temp->push(l1.info); 
    } 
    return *temp; 
} 

这是一个列表,推推动的物品,主要的例子:

int main(int arcg, char **argv) 
{ 
    List<T>l1,l2,l3; 
    for(int i=0;i<10;i++) 
    { 
     l1.push(i); 
     l2.push(i); 
     l3.push(i); 
    } 
    l3=l1&l2; 
} 

这种情况L3已经L1 & L2,但无线这会导致内存泄漏?

+1

我们需要更多的代码。像赋值运算符和&运算符一样能够帮助您。 – 2012-01-29 17:57:32

回答

2

不,应该罚款。原来的a1将被销毁并换成新的(这是a2 & a3的结果)。

但是你应该确保,如果A包含指针,拷贝构造函数,赋值操作符和析构函数是否正确为该类型定义,否则“原a1将被摧毁”可能还不够!

0

在A级,赋值运算符必须删除原始数据

class A { 
    A &operator=(const A &orig){ 
     if(&orig == this){ 
      return *this; 
     } 

     // here 
     if(data){ 
      delete []data; 
     } 

     // copy original data 
    } 
} 
+0

错过了为自己分配的检查,应该在删除之前进行复制。 – Lalaland 2012-01-29 17:59:59

+0

@EthanSteinberg谢谢,错过了。这是好的还是你有更好的主意? – Vyktor 2012-01-29 18:01:40

+0

为什么不好的复制和交换超载'='? – 2012-01-29 18:02:26

0

我相信只有一个内存泄漏,如果你这样做:

A *a1 = new A(1); 
a1 = a2 & a3; // Don't do this, it doesn't work 

只要有一个A1,A2 ,a3;如果你宣布他们是这样的话,这是不可能的。该函数在调用函数时为这些对象静态分配空间,并且在函数完成执行时(在弹出堆栈期间)它们会自动释放。

+0

虽然不会编译。你会做'* a1 = a2 &a3;'这是合法的。 – David 2012-01-29 18:06:50

0

赋值运算符的职责是,就在左侧相同的右手边的一个对象。如果它分配了内存,并且正在用右边的东西来替换内存,那么它会释放内存。在一般情况下,我发现它最容易实现的拷贝构造函数方面的赋值操作符和swap()成员函数:

T& operator= (T const& other) { 
    T(other).swap(*this); 
    return *this; 
} 

swap()成员函数只是做一个按成员交换。

+1

我认为'other'应该是通过副本进行复制和交换的。 – 2012-01-29 18:03:55

+0

@Als:不;他明确创建了一个副本。 'T(其他)' – 2012-01-29 18:04:51

+0

**应该做的**是通过'const'传递'other'!我会解决这个问题。按价值传递应该是有效的,并且避免需要明确的副本和副手,我不记得为什么我通常不这样做(尽管如此,也许这只是我应该修复的错误习惯)。 – 2012-01-29 18:08:45