2013-11-26 58 views
0

我有以下簡單的向量類,我可以在其中定義不同大小的向量並對它們進行求和;我已經重載了+運算符並且包含一個簡單的數據顯示方法desplegar();類被定義爲:當它們作爲C++參數傳遞給函數時被修改的對象

class Cvector{ 
    private: 
    int dim; 
    float * C; 
public: 
    Cvector(){}; 
    Cvector(int n){dim=n; C = new float[dim];}; 
    ~Cvector(){delete [] C;}; 
    int getdim(){return dim;}; 
    float getC(int i){ 
    if(i<dim && i>=0) 
     return C[i]; 
    else 
     return 0; 
    }; 

    void setC(int i, float x){ 
    if(i<dim && i>=0) 
     C[i]=x; 
    } 

    void desplegar(){ 
    cout<<"[ "; 
    for(int i=0;i<dim;i++) 
     cout<<getC(i)<<" "; 
    cout<<" ]"<<endl; 
    } 

    Cvector operator + (Cvector); 
}; 

Cvector Cvector::operator + (Cvector A){ 
    int n; 
    if(A.getdim()>dim) 
     n=A.getdim(); 
    else 
     n=dim; 

    Cvector temp(n); 
    for(int i=0;i<n;i++) 
     temp.setC(i,getC(i)+A.getC(i)); 
    return temp; 
} 

當我運行下面的代碼,一切正常:

Cvector X(2); 
Cvector Y(3); 

定義維度2的對象和3

X.setC(0,1); 
X.setC(1,4); 

Y.setC(0,0); 
Y.setC(1,6); 
Y.setC(2,9); 

增加相應的值(X代表2個,Y代表3個)

X.desplegar(); 
Y.desplegar(); 

Cvector T=Y+X; 
T.desplegar(); 

一切都顯示正確,直到這裏,T顯示向量Y和向量X,這正是我想要的總和。但是,當我運行

X.desplegar(); 

它只是從內存中顯示不相關的數據,似乎當它作爲參數傳遞給運營商+通過了對象X被修改,爲什麼會這樣?如果我使用指向這些對象的指針,這種情況不會發生,但它看起來並不直觀。

任何人都可以評論?

+0

*可能*你需要執行'operator ='或者該賦值可能會混淆你的一個傳入操作數。另外,你真的應該傳遞'const'引用而不是傳遞值並且瞭解[[three]的規則](http://en.wikipedia.org/wiki/Rule_of_three_(C++ _ programming))。 –

回答

1

當您用參數pass-by-value重載operator +時,會調用複製構造函數以實例化臨時對象。默認情況下,複製構造函數是原始對象的按位副本。並且就在方法返回之前,用戶定義的析構函數在臨時對象上被調用,在該對象上釋放底層存儲。

要更正代碼,請自行定義複製構造函數或通過引用傳遞參數。

請務必記住rule-of-three,即當您定義了任何析構函數,複製構造函數和賦值運算符時,請考慮在這三者之間定義其他值。

+0

謝謝,這是完全合理的! – user3035350

0

複製載體不正確。 tempoperator +的末尾自動調用其析構函數,導致T有一個懸掛指針。你可能會做類似於X的事情,很難說沒有看完整個程序。

1

問題出在您的operator+

Cvector Cvector::operator + (Cvector A) 

在這裏,你是通過使複製它經過第二個操作數(在你的情況是X)。此副本(A)將有它的C指針指向相同的內存作爲您X載體:

Cvector T=Y+X; 

operator+末,副本將被摧毀,析構函數會被調用,並且內存將被釋放。由於該內存由XX本身的副本共享,因此您將擁有垃圾。更改operator+所以它需要一個參考,一切都將正常工作:

Cvector Cvector::operator + (const Cvector & A) 

注意,它也是實現一個拷貝構造函數是個好主意。

+0

謝謝,是否有必要使它成爲一個常量? – user3035350

+0

@ user3035350,不,它不是 – SingerOfTheFall

0

Cvector沒有一個拷貝構造函數,所以默認的,將產生:

Cvector::Cvector(Cvector const & original) 
    : dim(original.dim), C(original.C) 
{} 

這確實一個副本,也就是說,你現在有相同的C指針的兩個對象。

所以,當你複製 X作爲參數傳遞給任何功能,出現這種情況:

Cvector x; 
// populate X 
// now call this: 
void foo(Cvector y) { // y is created as a copy of x 
} // y is destroyed 

當複製參數被破壞,它會刪除C,這是共享與原。


這些修改的話:

  1. 寫正確的拷貝構造函數和賦值操作符,執行深拷貝(被摧毀後,這將阻止拷貝從打破了原有的對象)
  2. 通當你不改變它們時通過const引用的參數
+0

Cop構造函數可以解決它,但傳遞參考是最快的方法! – user3035350

+0

複製構造函數應該被添加_anyway_,因爲沒有它,這個代碼非常脆弱。 – Useless

相關問題