【问题标题】:Regarding destructor in an array of objects关于对象数组中的析构函数
【发布时间】:2014-01-03 15:51:19
【问题描述】:

我有一个关于如何调用析构函数的问题。例如,我创建了以下 foo 类并提供了复制构造函数、析构函数并重载了赋值运算符。我创建了这个 foo 对象的动态数组,并使用运算符“=”来分配数组的各个元素。我很困惑,在赋值操作之后,立即调用析构函数,当我想访问新分配的对象中的数据时,我得到了非常混乱的结果。有什么建议吗?

#include <iostream>

using namespace std;
bool debug = true;

class foo{
private:
    int n;


    void init(int _n);
public:

    int* arr; // just to make it accessible so that we can tract the contents;

    foo(int _n);
    foo(int* _a, int len);
    foo(const foo & rhs);
    foo & operator=(const foo & rhs);
    ~foo();
};


void foo::init(int _n = 0){
    n = _n;
    arr = new int[n];
    for(int i = 0; i != n; i++) arr[i] = 0;
}

foo::foo(int _n = 0){
    init(_n);
}

foo::foo(int*_a, int len){
    init(len);
    for(int i = 0; i< len; i++) arr[i] = _a[i];
}

foo::foo(const foo &rhs){
    operator = (rhs);
}

 foo& foo::operator= (const foo &rhs){
     if(debug) cout<<"\nassignment operator overloaded";
     if (this != &rhs){
         if(n != 0) {
            n = rhs.n;
            delete [] arr;
            arr = new int[n];
            for(int i = 0; i < n; i++) arr[i] = rhs.arr[i];
         }
     }
     return *this;
}

foo::~foo(){
    if (debug)cout << "\ndestructor called\n";
    delete []arr;
}

int main(){

    { // a explicit block to see when the destructor is called;
        foo* f = new foo[4];
        int n = 4;
        int a[] = {0,1,2,3};
        for(int i = 0; i < n;i++) {
            cout<<i;
            f[i] = foo(a, i);
            cout<<f[i].arr[i]<<"\n"; // result is some seemingly random number;
        }
    }

    system("PAUSE");
}*

【问题讨论】:

  • 我已经修复了解构函数的使用,所以这是 googleable
  • \在构造一个对象之后它应该准备好了。

标签: c++ arrays


【解决方案1】:

当你这样做时:

f[i] = foo(a, i);

在赋值运算符的 RHS 上创建一个临时的 foo 对象。然后用于分配给操作员 LHS 上的foo。然后,它被销毁,因此它的析构函数被调用。

赋值后出现垃圾值的原因可能是数组中所有foos中的n0。你的赋值运算符坏了。你可能想看看copy and swap idiom

【讨论】:

    【解决方案2】:

    一个大不,不!将未初始化对象的初始化委托给赋值运算符不是一个好主意:

    foo::foo(const foo &rhs){
        operator = (rhs);
    }
    

    更好的是:

    foo::foo(const foo &rhs)
    :   n(rhs.n), arr(new int[n])
    {
        // copy rhs.arr to arr
    }
    
    // Note: Passing by value:
    foo& operator = (foo rhs) {
       std::swap(n, rhs.n);
       std::swap(arr, rhs.arr);
       return *this;
       // Note: The swapped rhs will do the cleanup in the destructor
    }
    

    您最终会减少编码和异常安全

    另一个问题是:

    cout

    您正在打印未定义的“结束”值 (arr[i] == arr[n])

    【讨论】:

    • 感谢您的输入,但我尝试根据您的建议修改我的代码,我仍然得到类似的有线号码。还有什么建议吗?
    • @XuanZhou 另一个问题是 'cout
    • 谢谢,我明白了。如果一开始我能想通就好了
    猜你喜欢
    • 2021-07-04
    • 2016-10-28
    • 2022-01-21
    • 2016-02-10
    • 2023-03-27
    • 2011-11-21
    • 2013-09-27
    • 2012-12-26
    • 2018-08-14
    相关资源
    最近更新 更多