2010-01-28 3 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);'? –

+0

@ Кирилл. Правда. Он не компилируется. Не удается найти 'getX' и' getY'. –

ответ

1

Я думаю, проблема в вашем операторе присваивания. Как выглядит оператор =?

Кажется, что оператор = вызывает в нем себя. Возможно ли, что фрагмент кода взят из тела оператора = сам?

Если это решение, необходимо изменить код (внутри оператора =) так, чтобы он использовал копию ctor. Каноническая форма выглядит следующим образом:

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

(см Exceptional C++ Херб Саттер для более подробной информации)

+0

Хммм. Этот ответ дублирует ответ R Samuel Klatchko. Принять дублированный ответ? –

6

Эта линия:

tempVector2 = Vector2f(tempVector1); 

бы вызвать оператор =, а не конструктор копирования. Вы определяете оператор =, который делает что-то неловкое?

Кроме того, ваш код работал отлично для меня как с g ++ 4.3.2 на Linux, так и с g ++ 4.2.1 на Mac (после того, как я определил getX, getY, преобразовал DebugLog в printf и использовал float вместо GLfloat).

+2

Я бы тоже сказал то же, какой-то код не виден. Из приведенного выше кода я не вижу никакой проблемы. – jdehaan

+0

Спасибо, что проблема не в конструкторе копирования, а в операторе присваивания. –

+0

Не совсем точно. Во-первых, он будет ссылаться как на явное приведение (которое * будет * ссылаться на конструктор копирования). Во-вторых, кроме того, он может вызывать конструктор копирования столько раз, сколько требуется при инициализации параметра 'operator ='. – AnT

1

Во втором случае вы выполняете задание, а не строительство. Вы не указали свою собственную версию оператора копирования, что означает, что компилятор предоставит вам один. Оператор копирования Назначения компилятора при условии, будет неявно объявлен как

Vector2f& operator =(const Vector2f& rhs); 

Заметит, что единственный параметр этого оператора имеет тип опорных к-Const.

В вашем коде вы настаиваете на предоставлении временного rvalue объекта типа Vector2f с правой стороны назначения.

tempVector2 = Vector2f(0.0f, 0.0f); 

Это означает, что опорный параметр operator = инициализируется с временным RValue типа класса. Согласно его спецификации языка (8.5.3/5), компилятору разрешено копировать этот временный объект столько раз, сколько он хочет, прежде чем фактически привязать ссылку. В конце концов он должен прекратить копирование и, наконец, вызвать оператора. Обычно компилятор не сходит с ума от копирования (большинство из них вообще не копируют), однако в вашем случае это, похоже, проблема. По какой-то причине ваш компилятор блокируется в бесконечном цикле копирования, не останавливая его. Я не знаю, что вызывает это. Может быть ошибкой в ​​компиляторе.

Обратите внимание, что даже в

tempVector2 = Vector2f(tempVector1); 

вы до сих пор поставляет правую в виде временного RValue. Rvalue является результатом явного приведения в Vector2f, который вы по какой-то причине положили туда. Я понятия не имею, почему вы это сделали. Если проблема действительно в компиляторе (а не в коде, вы не показываете нам), я уверен, что если вы только

tempVector2 = tempVector1; 

задание будет осуществляться без каких-либо проблем. Это на самом деле то, как вы можете обойти проблему, если она окажется ошибкой в ​​компиляторе: прекратите использовать временные ресурсы в качестве аргументов для оператора copy-constructor и copy-assign.

0

Запустите его под IDE. Когда он находится в цикле, нажмите кнопку «Пауза». Вы точно увидите, в чем проблема. Here's why.