указатели — C ++ хранит ссылку на член класса в векторе

Рассмотрим объект 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);

2

Решение

Ваша ошибка в хранении мышления &drag.pos поможет вам отслеживать dragпозиции, в то время как на самом деле вы храните адрес, который станет бессмысленным к концу этой области. поскольку drag является локальной переменной, находящейся в стеке, она исчезнет к концу области, в которой она была создана. Даже сохраняя адрес копии drag это создается вектором, когда вы push_back не поможет в этом случае, так как он также станет недействительным, когда вектор увеличится в физическом размере и должен будет переместить все свои вещи в другое место в памяти.

Что вы можете сделать, так это убедиться, что фактический объект Drag, который вы помещаете в вектор, остается единственным вокруг, размещая его в куче и вставляя (умный) указатель на него в вектор. Таким образом, вы можете сохранить указатель на его внутреннюю pos в векторе, как вы сделали, и он будет действителен, пока другой вектор.

3

Другие решения

Вы не можете хранить ссылки внутри вектора, но вы можете хранить 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).

3

По вопросам рекламы [email protected]