0

我正在编写一个数学库作为实践练习。我在重载 = 运算符时遇到了一些问题。当我调试它时,我注意到对 vertex1 = vertex2 的调用改为调用复制构造函数。

在头文件中我有:

//constructors
vector3();
vector3( vector3 &v );
vector3(float ix, float iy, float iz);

//operator overloading
vector3 operator =(vector3 p);
....

在我实现的源文件中:

vector3 vector3::operator =(vector3 p)
{
    vector3 v3;
    v3.x = p.x;
    v3.y = p.y;
    v3.z = p.z;
    return v3;
}

后来我有一个叉积方法,我想像这样使用它:

vector3 v3;
v3 = v1.crossProduct(v2);

错误消息是:error: no matching function for call to `vector3::vector3(vector3)' 但我不想调用复制构造函数。

4

6 回答 6

4

您的代码中有错误。您的复制构造函数必须采用const&. 该引用将避免制作副本(作为复制构造函数,您将无法做到这一点),并且应该是const因为您没有修改它:

vector3(const vector3&);

临时变量可以绑定到const&,但不能绑定到可变引用。也就是说,使用您的代码,您可以执行以下操作:

vector3 a;
vector3 b(a);

但不是:

vector3 a(some_calculation()); // some_calculation returns a vector3

另外,你operator=的不正确。与复制构造函数一样,它通常应采用const&但应返回对 的引用this。这就是链接的工作原理:

int a, b, c;
a = b = c = 0;
// a.operator=(b.operator=(c.operator=(0)));

返回一个临时的是非正统的,并没有完成任何事情。在您的情况下,您可以一遍又一遍地分配并且永远不会更改值。奇怪

vector 3 a, b;
a = b; // doesn't change a...?!

operator=需要改变this

于 2010-02-14T16:39:33.730 回答
2

向量3(向量3 &v);

那真的应该是vector3( const vector3 &v );

由于您返回一个临时值,因此您必须调用一个接受 const 引用的复制构造函数。

于 2010-02-14T16:25:58.643 回答
2

我不想调用复制构造函数。

你想要什么无关紧要。你需要一个拷贝构造函数。operator =在这种情况下不会被调用,复制构造函数是。另外,签名错了,应该是

vector3& operator =(vector3 const& other);

参数也可以按值传递(但这是一个高级技巧……)但返回值确实必须是非常量引用。

(您的复制构造函数的签名也是非常规的,请参阅 James 的回答。)

于 2010-02-14T16:34:35.517 回答
1

改为使用引用,vector3 vector3::operator =(vector3 p)因此您无需创建副本。

vector3& vector3::operator =(vector3& p);

无论如何,您首先不想创建复制的对象。

于 2010-02-14T16:25:27.210 回答
1

在 C++ 中,根据您是否希望您的对象可复制(即可分配给另一个变量)来做两件事之一,这是一个很好的做法。如果您这样做,则需要同时提供赋值运算符和复制构造函数。例如:

class Point
{
public:
    Point ()                          { }
    Point (int x, int y)              : mX(x), mY(y) { }
    Point (const Point& p)            : mX(p.mX), mY(p,mY) { }

    Point& operator = (const Point& p)    { mX = p.mX; mY = p.mY; return *this; }

    int X () const                    { return mX; }
    int Y () const                    { return mY; }

private:
    int mX;
    int mY;
};

如果您不希望它可复制,您可以将复制构造函数和赋值运算符的原型放在私有部分中,并且不提供实现。任何复制它的尝试都会产生编译器错误。

每当您使用这种代码时:

Point P = anotherP;

将调用复制构造函数。如果您使用这种类型的代码:

Point P;
P = anotherP;

将调用分配运算符。

希望有帮助。

于 2010-02-14T16:46:23.803 回答
0

当您“按值传递”时,就像您在运算符 = 的定义中一样,会制作类型的副本以用作方法的本地值。没有调用您的运算符,因为系统找不到采用 vector3 的构造函数——您已经定义了一个采用 vector3& 的复制构造函数。

因此,正如其他人所说,您要做的是将您的 operator = 定义为

const vector3& p

您还应该更新您声明的复制构造函数以采用 const vector3 。

于 2010-02-14T16:42:15.483 回答