visual-studio - 關於c++物件陣列初始化時產生的臨時變數析構問題?
PHP中文网
PHP中文网 2017-05-16 13:24:00
0
3
1059

第一種情況:

建立c++物件數組時候,如果透過初始化列表賦值,會產生臨時變量,但為什麼不會呼叫析構函數
程式碼如下:

#include <iostream>
    using namespace std;
    class Point
    { public:
        Point():x(0),y(0)
        {   cout<<"Default Constructor called.\n";}
        Point(int xx,int yy):x(xx),y(yy)
        {   cout<< "Constructor called.\n";  }
        ~Point()
        {   cout<<"Destructor called.\n";    }
        void Move(int xx,int yy)    {  x=xx;  y=yy;   }
    private:
        int  x,y;
    };
    int main()
    {
        Point A[2]={Point(1,2),Point()};
        cout<<"hello"<<endl;
        return 0;
    }

輸出結果為:


#其中,Point A[2]={Point(1,2),Point()};透過兩個暫存變數初始化物件陣列A,之後為什麼不會呼叫析構函數將其析構,結果中並未呼叫這兩個臨時物件的析構函數。

第二種情況:
分別為陣列的每個元素顯示呼叫建構函數,就會自動呼叫析構函數:
程式碼如下:

#include <iostream>
using namespace std;
class B
{
    int x, y;
public:
    B();
    B(int i);
    B(int i, int j);
    ~B();
    void Print();
};
B::B() :x(0), y(0)
{
    cout << "Default constructor called.\n";
}
B::B(int i) : x(i), y(0)
{
    cout << "Constructor 1 called.\n";
}
B::B(int i, int j) : x(i), y(j)
{
    cout << "Constructor 2 called.\n";
}
B::~B()
{
    cout << "Destructor called.\n";
}
void B::Print()
{
    cout << "x=" << x << ", y=" << y << endl;
}
int  main()
{
    B *p;
    p = new B[3];
    cout << "*******" << endl;
    p[0] = B();
    p[1] = B(7);
    p[2] = B(5, 9);
    for (int i = 0; i < 3; i++)
        p[i].Print();
    cout << "*******" << endl;
    delete[]p;
}



運行結果如下:


可見在為每個陣列元素呼叫建構函式初始化後,臨時變數析構了。


綜上兩種情況都是臨時變量,但是為什麼一個會自動析構,另一個不會,求解! ! !

PHP中文网
PHP中文网

认证0级讲师

全部回覆(3)
黄舟

重新查了一下資料,同時自己動手時實踐了一下,更正錯誤
原因:對象賦值是將右側的對象的成員的值複製到左邊的對象,然後釋放右邊的對象
—————— ————
每一次調用B()(有參或無參)都創建了一個臨時對象
情況一.創建臨時對象(保存在A)後未被賦值,也就不存在釋放右側對象的過程,A中的對象存活至main()結束
情況二.對p數組賦值,創建臨時對象賦值給原來的對象,原來的對象(即初始化p時自動創建的臨時對象)僅僅是被賦值,右側的臨時變數被析構,delete時析構p中保存的臨時物件
——————————
至於為什麼A中右邊的臨時變數沒有被析構,你可以試試在構造函數中輸出this,然後再輸出一下A中保存的物件的引用你就知道了,如果還有錯誤或不懂請指出,我會及時更正或解答

小葫芦

1.棧空間申請變數的生存期,在超出作用範圍時銷毀,這個作用範圍在main函數。
2.delete的不用多說。首先B[3]也是堆疊空間,但你重新賦值後他的,使命就結束了,儘早回收。

大家讲道理
Point A[2]={Point(1,2),Point()};

數組A是函數局部變量,記憶體分配在堆疊區,Point(1,2),Point()這兩個也是局部變量,同樣分配在堆疊區。這時候編譯器一般會做個最佳化,減少一次記憶體回收與分配。


p = new B[3];
cout << "*******" << endl;
p[0] = B();
p[1] = B(7);
p[2] = B(5, 9);

數組p記憶體空間是動態分配的,處於堆區。 B(0),B(7),B(5, 9)三個是分配在堆疊區上的局部變數。
雙方記憶體分配位置不同,編譯器也不可能做最佳化,只能老實地析構。

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板