Рассмотрим объект Drag:
class Drag {
public:
Drag(ofVec3f _pos);
ofVec3f pos;
}
Позиция сохраняется при создании нового экземпляра:
Drag::Drag(ofVec3f _pos) {
pos = _pos;
}
Положение обновляется при перемещении мыши:
void Drag::mouseMoved() {
pos.x = ofGetMouseX();
pos.y = ofGetMouseY();
}
В основном классе приложения (testApp в openframeworks):
class testApp : public ofBaseApp {
public:
vector<Drag> drags;
vector<ofVec3f *> points;
}
Создайте Drag, когда мышь нажата, и сохраните его положение в векторе, называемом точками:
void testApp::mousePressed(int x, int y, int button) {
Drag drag = Drag(ofVec3f(ofGetMouseX(), ofGetMouseY(), 0));
drags.push_back(drag);
points.push_back(&drag.pos);
}
Теперь, когда перетаскивание перемещено, я вижу, как обновляется его положение, но точки [0] не меняются:
void testApp::update(){
if (!drags.size()) return;
cout << drags[0].pos.x << ", " << drags[0].pos.y << endl;
cout << &points[0]->x << ", " << &points[0]->y << endl;
}
Если тип точек vector<ofVec3f>
кажется, что points [0] является копией начальных drags [0] .pos. Если это vector<ofVec3f *>
тогда, кажется, хранить в памяти адрес, который равен &тащить, тянуть.
Как сделать так, чтобы точки [0] указывали на drags [0] .pos и обновляли значения x, y при обновлении drags [0] .pos.x и drags [0] .pos.y?
Как я могу сделать очки [0] быть ссылка тащить [0] .пос?
Редактировать: Спасибо Йонилеву за то, что он указал мне правильное направление. Вот рабочий пример, обновленный с использованием std :: list:
// testApp.h
list<Drag> drags;
vector<ofVec3f *> points;
// testApp::mousePressed
drags.push_back(Drag(ofVec3f(ofGetMouseX(), ofGetMouseY(), 0)));
points.push_back(&drags.back().pos);
Ваша ошибка в хранении мышления &drag.pos
поможет вам отслеживать drag
позиции, в то время как на самом деле вы храните адрес, который станет бессмысленным к концу этой области. поскольку drag
является локальной переменной, находящейся в стеке, она исчезнет к концу области, в которой она была создана. Даже сохраняя адрес копии drag
это создается вектором, когда вы push_back
не поможет в этом случае, так как он также станет недействительным, когда вектор увеличится в физическом размере и должен будет переместить все свои вещи в другое место в памяти.
Что вы можете сделать, так это убедиться, что фактический объект Drag, который вы помещаете в вектор, остается единственным вокруг, размещая его в куче и вставляя (умный) указатель на него в вектор. Таким образом, вы можете сохранить указатель на его внутреннюю pos
в векторе, как вы сделали, и он будет действителен, пока другой вектор.
Вы не можете хранить ссылки внутри вектора, но вы можете хранить std::reference_wrapper<ofVec3f>
,
std::vector< std::reference_wrapper<ofVec3f> > v;
ofVec3f vec;
v.push_back(std::ref(vec));
Хранение указателя также работает. Вам просто нужно разыменовать это правильно с operator*
или же operator->
,
std::vector< ofVec3f* > pv;
ofVec3f vec;
pv.push_back(&vec);
pv.front()->x;
О равенстве адресов То, что адреса совпадают с адресом перетаскиваемого объекта, является нормальным. Вектор является первым членом, и поэтому они имеют один и тот же адрес (это гарантированно только в случае типов POD).