将声明和初始化与超载`=`相结合

Combining declaration and initialization with overloaded `=`

本文关键字:相结合 超载 声明 初始化      更新时间:2023-10-16

我是C 的新手(但不是编程的新手 - 我非常了解Java),所以这可能有一个简单的答案,我只是在忽略。

简而言之:写作之间的区别(如果有的话):

classType a = b;

和写作

classType a;
a = b;

特别是当b是函数中的参考变量以及=被重载时?

详细信息/背景:

我正在研究一个自定义vect类,该类将(最终)持有n-tuples在R^n中的表现(即数学式向量,而不是STL风格的向量)。因此,我已经将=运算符重载,将组件从rhs复制到lhs

但是,我发现,当我的RHS是函数中的参考变量时,组合的声明/初始化使RHS和LHS参考 same same object ,而单独的初始化将它们保持为不同的对象

在下面的程序中,这可以证明这是因为v2 = v1 * 10在我使用单线vect a = b时会导致v2v1等于v1*10,但是当我在*的定义中编写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;
}

区别在于 vect a = b;执行复制初始化,而 vect a; a = b; cop 复制分配。复制初始化调用copper copper copper consenter,而复制分配呼叫超载operator=

在您的代码中,您的副本分配操作员将一个向量的元素复制到另一个元素中,这很好。但是,您的复制构造函数只需设置LHS的baseArray即可指向与RHS相同的内存块,而无需复制任何向量元素。当两个指针指向相同的内存时,当然修改一个也会修改另一个内存。