【发布时间】:2014-02-19 03:31:48
【问题描述】:
我是 C++ 新手(但对编程并不陌生——我非常了解 Java),所以这可能有一个简单的答案,我只是忽略了。
简而言之:写作和写作的区别是什么(如果有的话):
classType a = b;写作
classType a; a = b;特别是当
b是函数中的引用变量并且=被重载时?
详情/背景:
我正在开发一个自定义的 vect 类,它(最终)将保存 n 元组,其行为类似于 R^n 中的向量(即数学风格的向量,而不是 STL 风格的向量)。因此,我重载了 = 运算符以将组件从 rhs 复制到 lhs。
但是,我发现,当我的 rhs 是函数中的引用变量时,组合声明/初始化使 rhs 和 lhs 引用 相同的对象 ,而单独的初始化将它们保持为不同的对象。
在我下面的程序中,当我使用单行 vect a = b 时,v2 = v1 * 10 导致 v2 和 v1 都设置为等于 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;
}
【问题讨论】:
-
问题:为什么要动态分配
baseArray?如果它总是 3 你不需要(你应该使用std::array<double, 3>。如果它的大小不同,你应该将指针存储在std::unique_ptr<double>或使用std::vector<double> -
@Borgleader 我想最终使它成为一个可变长度数组,但认为最好首先使用固定长度的情况(为了简单起见)。我猜测 C++ 对动态大小数组的处理与 Java 类似,但显然情况并非如此。 (tl;dr:我试图让它轻松扩展到长度为
n的数组,但似乎我还没有这样做。):) -
你有,但你正在做额外的工作(即:自己管理内存)。通过使用向量,您将拥有相同的功能,而无需处理内存管理。 (您也可以使用模板)。
-
@Borgleader 我想我最终可能会使用
vector... 我确实考虑过模板,但我计划使用这个类,这样我在编译时并不总是知道数组的长度时间。 (我的理解是模板参数需要在编译时知道。) -
vect result = v调用 copy-constructor,而不是您重载的 copy-assignment 运算符。您还需要实现复制构造函数。
标签: c++ initialization operator-overloading assignment-operator