0

我是C++的新手(但對編程並不陌生 - 我非常瞭解Java),所以這可能只是一個簡單的答案,我只能忽略它。結合聲明和初始化重載`=`

問題一言以蔽之:什麼(如果有的話)是寫作的區別是:

classType a = b; 

,寫

classType a; 
a = b; 

特別是當b是一個參考變量的函數當=超載?

詳細信息/背景:

我工作的一個自定義vect類,這將(最終)持有正元組表現得像R^n向量(即數學式載體,不是STL風格的向量)。因此,我已經超載了=運營商,將組件從rhs複製到lhs

然而,我發現,當我RHS是一個函數的引用變量,聯合聲明/初始化使RHS和LHS引用同一對象,而單獨的初始化讓他們爲不同的物體

在下面我的程序,這是證明爲v2 = v1 * 10結果按v2v1被設置爲v1*10當我使用單行vect a = b,但其工作方式,當我在*定義寫vect a; a=b預期。

最少可編譯例子:

我爲它的長度道歉,但這就像我可以在第一次嘗試把它相比下來。我會繼續尋找減少的方法。

該問題發生在運算符*的超載。我已經評論過需要進行哪些更改才能展示問題。

#include<iostream> 
#include<string.h> //For toString method 
#include<sstream> //For toString method 

//=================================================== 
// Namespace for organization 
namespace linalg { 
    class vect { 
     private: 
      //int length; 
      double* baseArray; 
     public: 
      //Constructor 
      vect() { baseArray = new double[3]; } 

      //TODO: Change so edits to arrayArg do not show up in the baseArray. 
      vect(double arrayArg[3]) { baseArray = arrayArg; } 

      //Returns a string for printing 
      std::string toString(); 

      //Returns the element at given index 
      double getElementAt(int) const; 

      //Operator overloading: 
      vect& operator=(const vect &rhs); 
      friend vect operator*(double num, const vect &v); 
    }; 

    //=================================================== 
    // General Methods 
    // elementAt : return s the given element. 
    double vect::getElementAt(int i) const { 
     return baseArray[i]; 
    } 

    // toString : behaves like Java convention: 
    //toString : gives string representation 
    std::string vect::toString() { 
     std::string retVal; 

     retVal.append("["); 
     for (int i = 0; i < 3; i++) { 
      //Convert the number to a string 
      std::ostringstream num; 
      num << baseArray[i]; 

      //Append the number to the return value 
      retVal.append(num.str()); 

      //Comma separated 
      if (i < 3-1) retVal.append(", "); 
     } 
     retVal.append("]"); 

     return retVal; 
    } 

    //=================================================== 
    // Operator overloads 
    //Overload '=' : copies the other vector into this vector 
    vect& vect::operator= (const vect &rhs) { 
     //Check for self-assignment: 
     if (this == &rhs) { 
      return *this; 
     } 

     //Copy the rhs into this vector 
     for (int i = 0; i < 3; i++) { 
      baseArray[i] = rhs.getElementAt(i); 
     } 

     return *this; 
    } 

    //Overload scalar multiplication 
    vect linalg::operator*(double num, const vect &v) { 
     //CHANGE THIS to a single-line assignment/initialization, and the problem occurs. 
     vect result; 
     result = v; 

     for(int i = 0; i < 3; i++) { 
      result.baseArray[i] *= num; 
     } 

     return result; 
    } 
}; 

using namespace linalg; 
using namespace std; 

int main() { 
    double a[3] = {2, 4, 8}; 
    double b[3] = {5, 1, 9}; 

    vect v1(a); 
    vect v2(b); 

    v1 = 10*v2; 

    cout << v1.toString() << endl; 
    cout << v2.toString() << endl; 

    system("pause"); //Pause the windows terminal 

    return 0; 
} 
+0

問題:你爲什麼動態分配'baseArray'?如果它總是3,你不需要(你應該使用'std :: array '。如果它的大小不同,你應該將指針存儲在'std :: unique_ptr '或使用'std :: vector ' – Borgleader

+0

@Borgleader我最終想把它變成一個可變長度的數組,但認爲最好先用一個固定長度的例子(爲了簡單起見)。我猜測C++處理動態大小的數組類似於Java,但顯然情況並非如此(tl; dr:我試圖使它容易擴展到長度爲n的數組,但看起來我沒有這樣做)':)' – apnorton

+0

好吧,但你正在做額外的工作(即:自己管理記憶)。通過使用矢量,您可以擁有相同的功能,而無需處理內存管理。 (你也可以使用模板)。 – Borgleader

回答

1

不同的是,vect a = b;執行拷貝初始化vect a; a = b;執行拷貝賦值。複製初始化調用複製構造函數,而複製分配調用過載operator=

在你的代碼中,你的拷貝賦值操作符將一個向量的元素拷貝到另一箇中,這很好。但是,您的拷貝構造函數只需將LHS的baseArray設置爲指向與RHS相同的內存塊,而不需要複製任何矢量元素。當兩個指針指向相同的內存時,當然修改一個也會修改另一個。