2013-03-22 68 views
1

我应该在复制构造函数和/或赋值运算符中释放动态数组(分配在构造函数中)吗?动态数组解除分配(赋值运算符与复制构造函数)

struct Test 
{ 
    const size_t n; 
    int* xs; 

    Test(const size_t n) 
    : n(n) 
    , xs(new int[n]) 
    { } 

    Test(const Test& other) 
    : n(other.n) 
    , xs(new int[n]) 
    { 
    memcpy(xs, other.xs, n * sizeof(int)); 
    } 

    Test& operator=(const Test& other) 
    { 
    n = other.n; 
    delete[] xs; 
    xs = new int[n]; 
    memcpy(xs, other.xs, n * sizeof(int)); 
    } 

    ~Test() 
    { 
    delete[] xs; 
    } 
}; 

void main() 
{ 
    Test a(10); 
    Test b(a); 
    Test c(20); 
    c = b; 
} 

正如你可以看到,我想,你必须在delete[]赋值操作符执行数组(因为它已经被施工的地方多数民众赞成被分配给对象的过程中分配)。我认为在复制构造对象时不需要释放数组,因为它尚未构造。

问题是,在Application Verifier下运行上面的应用程序时,无论是否存在delete[]operator=或没有,都显示无内存泄漏。应用程序在两种情况下运行正常。

那么,我应该在delete[] xs的拷贝构造函数中,赋值运算符,还是两者都不?

+0

'Test&operator =(const Test&other) :n(other.n)'编译?是的,你应该。 – 2013-03-22 10:23:39

+0

@LuchianGrigore不,我输入它没有编译(我没有在我浏览的计算机上的编译器)。感谢您的注意! – 2013-03-22 10:26:53

+0

@LuchianGrigore但是为什么Application Verifier在两种情况下都没有显示内存泄漏?这不是一个值得信赖的工具吗? – 2013-03-22 10:27:43

回答

0

一般来说,手动内存管理是不好的的想法。你不应该这样做,你应该更喜欢std::vector<>或其他容器类,除非你有充分的理由不这样做。这说...

因此,我应该删除拷贝构造函数,赋值运算符,或两者兼得的[] xs?

在丢失指向该数组的最后一个指针之前,您应该为delete[]分配new[]。否则,你会泄漏。

实际上,由于您要删除的数组是由您的类拥有和封装的,这意味着您必须在赋值运算符重载中将其指定为delete[](在将指针指派给新数组之前,只有对前一个的引用)和析构函数中(当你​​处理对象然后丢失对封装数组的唯一现有引用时)。如你所说,复制构造函数是一个构造函数,指针之前并没有引用任何已分配的资源(实际上,这里没有“之前”,对象的生命周期甚至还没有开始):因此,这里不仅不需要delete[],这是错误的。

另请注意,为避免悬空指针和可能的未定义行为,您应确保您的类确实是封装数组的唯一所有者。否则,该类的外部代码可以是delete[],或者保存指向它的指针,这些指针会变成悬挂的。因此,您不应使xs数据成员public

+0

谢谢,我从现在开始坚持。我很担心Application Verifier会显示什么,但你的回答显然对我有意义,所以把它拧紧。 – 2013-03-22 10:32:38

+0

@EgorTensin:是的,我想说的也是。或者发布一个具体问题,询问为了使应用程序验证程序检测泄漏需要做些什么。不幸的是,我不知道这个工具,所以我无法帮助。 – 2013-03-22 10:34:55

+0

考虑到你的''std :: vector''的建议,欢迎你查看这个问题的评论(如果你感兴趣的话)。 – 2013-03-22 10:38:24

相关问题