類物件作為實參傳入函式,函式是複製物件還是直接使用物件的問題

FlyingFish_208發表於2019-03-03

今天遇到了這樣一個問題:

include<iostream>;
using namespace std;
class A{
private:
    int*p;
public:
    A(int n){ p=new int[n]; };
    ~A(){
        cout<<"呼叫解構函式"<<endl;
        delete p;
    }

};
void Fuc(A a){
    cout<<"進入函式Fuc"<<endl;
}

int main(){
    A a(5);
    Fuc(a);
	return 0;
}

使用的是CLion書寫編譯的。
輸出視窗報錯:

進入函式Fuc
呼叫解構函式
呼叫解構函式
test(12153,0x1198035c0) malloc: *** error for object 0x7fe295400620: pointer being freed was not allocated
test(12153,0x1198035c0) malloc: *** set a breakpoint in malloc_error_break to debug

設定斷點後發現,類A的物件a在Fuc結束後析構了一次,在main函式return 0;的時候又析構了一次。
我當時的問題是:a的生存週期不應該是整個main函式嗎?a作為實參傳入Fuc,Fuc應該是複製一份來使用,不應該在Fuc結束了之後直接把main裡的a析構了呀?
問同學後發現了錯誤。先附上解決方案:

#include<iostream>
using namespace std;
class A{
private:
    int*p;
    int l;
public:
    A(int n){
        p=new int[n];
        l=n;
        cout<<"構造"<<endl;
    };
    A(const A& C){
        cout<<"拷貝函式"<<endl;
        p = new int[C.l];
        l=C.l;
        int i;
        for(i=0;i<l;i++){
            p[i]=C.p[i];
        }
    }
    ~A(){
        cout<<"呼叫解構函式"<<endl;
        delete p;
    }

};

void Fuc(A a){
    cout<<"進入函式Fuc"<<endl;
}
int main(){
    A a(5);
    Fuc(a);

}

輸出:
構造
拷貝函式
進入函式Fuc
呼叫解構函式
呼叫解構函式
Process finished with exit code 0

解決的方法就是寫一個拷貝函式(建構函式的過載)。

“問題源於沒有重寫拷貝函式,類的內部變數如果只是int,char等的基本型別那麼編譯器可以自動寫拷貝函式,但是int *是陣列還是指向int的指標無法被編譯器識別,所以必須自己寫拷貝函式 。 在沒有拷貝函式的情況下,編譯器無法複製這個類所以那個func就沒有複製。”

感謝跑的飛快的田學長!?

相關文章