2010-01-28 78 views
2

我传递一个值来复制构造函数作为引用,但正在调用一个无限循环。复制构造函数调用一个无限循环

这里是我的类:

class Vector2f{ 
private: 
    GLfloat x; 
    GLfloat y; 

public: 
    Vector2f(); 
    Vector2f(const GLfloat _x, const GLfloat _y); 
    Vector2f(const Vector2f &_vector); 

    ~Vector2f(); 
}; 

这里的实现方法:

Vector2f::Vector2f(): 
     x(0.0f), 
     y(0.0f) 
{ 
    DebugLog("Vector2f constructor"); 
} 

Vector2f::Vector2f(const GLfloat _x, const GLfloat _y): 
     x(_x), 
     y(_y) 
{ 
    DebugLog("Vector2f constructor(%f, %f)", _x, _y); 
} 


Vector2f::Vector2f(const Vector2f &_vector): 
     x(_vector.getX()), 
     y(_vector.getY()) 
{ 
    DebugLog("Vector2f copy constructor"); 
} 

Vector2f::~Vector2f() 
{ 

} 

以下是我访问类:我得到

Vector2f tempVector1 = Vector2f(0.0f, 0.0f); 
DebugLog("tempVector1 initialized"); 

Vector2f tempVector2; 
tempVector2 = Vector2f(0.0f, 0.0f); 
DebugLog("tempVector2 initialized"); 

结果:

Vector2f constructor(0.000000, 0.000000) 
tempVector1 initialized 
Vector2f constructor 
Vector2f constructor(0.000000, 0.000000) 
Vector2f copy constructor 
Vector2f copy constructor 
Vector2f copy constructor 
... 

尝试初始化以前创建的对象时发生无限循环。 如果我尝试tempVector1复制到tempVector 2无限循环的发生,以及:

Vector2f tempVector2; 
tempVector2 = Vector2f(tempVector1); 

它为什么会发生,我怎么能阻止它进入一个无限循环?

预先感谢您。

+2

难道你不忘记Vector2f(const Vector2f&_vector)中的'&';'? – 2010-01-28 08:39:46

+0

@Kirill。真正。它不会编译。找不到'getX'和'getY'。 – 2010-01-28 08:48:39

回答

1

我认为问题出现在您的赋值运算符中。 运营商=看起来像什么?

看来,运营商=正以某种方式称他为自己。代码片段是否可能来自operator = body本身?

如果是这样,解决方案是更改代码(在operator =内部),以便它使用copy ctor。该规范形式如下:

Vector2f temp = Vector2f(arg); 
swap(*this, temp) // You need to implement a swap method 
return *this; 

(详情请参见Exceptional C++由香草萨特)

+0

嗯。这个答案重复了R Samuel Klatchko的回答。接受重复的答案? – 2010-01-28 08:54:41

6

这条线:

tempVector2 = Vector2f(tempVector1); 

将调用运营商=,而不是拷贝构造函数。你是在定义一个运算符=这是在做一些古怪的事情吗?我的g ++ 4.3.2和Mac上的g ++ 4.2.1(在我定义了getX,getY,将DebugLog转换为printf和使用float而不是GLfloat后),你的代码对我来说工作得很好。

+2

我也会这么说,有些代码是不可见的。从上面显示的代码中,我看不到任何问题。 – jdehaan 2010-01-28 08:45:14

+0

谢谢问题不在复制构造函数中,而是在赋值运算符中。 – 2010-01-28 08:49:16

+0

不完全准确。首先,它会调用两者,因为显式强制转换(这将*调用复制构造函数)。其次,在初始化'operator ='的参数时,它可以根据需要多次调用拷贝构造函数。 – AnT 2010-01-28 15:11:32

1

在您正在执行任务,而不是建设的第二种情况。您尚未定义自己的版本复制操作符,这意味着编译器将为您提供一个。编译器提供的拷贝赋值运算符将被隐式声明为

Vector2f& operator =(const Vector2f& rhs); 

需要注意的是该运营商的唯一参数有一个参考给const类型。

在您的代码中,您坚持要在作业的右侧提供临时右值类型为Vector2f的对象。

tempVector2 = Vector2f(0.0f, 0.0f); 

这意味着operator =的基准参数与类类型的临时右值初始化。根据他的语言规范(8.5.3/5),允许编译器在实际附加引用之前多次复制该临时对象。最终它必须停止复制并最终致电运营商。通常编译器不会因为复制而发疯(大多数情况下根本不复制),但在你的情况下,这似乎是问题所在。出于某种原因,您的编译器被锁定在一个无限的复制循环中,永不停止它。我不知道是什么原因造成的。可能是编译器中的错误。

注意,即使在

tempVector2 = Vector2f(tempVector1); 

你在一个临时右值的形式仍然提供了右侧。右值是由于某种原因放在那里,你明确地转换成Vector2f的结果。我不知道你为什么这样做。如果问题确实是在编译器(而不是在你的代码不向我们展示),我敢肯定,如果你做到这

tempVector2 = tempVector1; 

分配将不会出现任何问题来进行。实际上,如果事实证明这是编译器中的错误,那么您可以如何解决该问题:停止使用临时文件作为复制构造函数和复制赋值运算符的参数。

0

在IDE下运行它。当它在循环中时,按下“暂停”按钮。你会看到确切的问题。 Here's why.