Заполните вектор ссылками на другой вектор - PullRequest
0 голосов
/ 01 октября 2018

У меня есть вектор структур, которые представляют точки (все точки).Этот вектор содержит весь набор точек на данной плоскости (в этом примере он содержит четыре точки).Каждая структура содержит пару целых чисел, представляющих точку, флаг, а также еще один вектор точек, который содержит все остальные точки на плоскости.

Что я хочу сделать, это выбрать точку из списка предпочтенийточка, измените ее флаг и примените это изменение к точке в векторе allPoints.Я думаю, мне нужен вектор ссылок или что-то подобное.Вот пример того, о чем я говорю:

#include <iostream>
#include <string>
#include <vector>
#include <utility>

using namespace std;

struct Point {
    pair<int,int> p;
    vector<Point> prefs;
    bool flag = true;
};

void fillVectors(vector<Point> & allPoints);
void printState(vector<Point> & allPoints);

int main()
{
    vector<Point> allPoints; 

    fillVectors(allPoints);
    printState(allPoints);

    // I want to go into the preference list of any given point, select a point, and change its flag. This change
    // should be reflected in the allPoints vector, not just the preferences vector

    allPoints[0].prefs[2].flag = false;

    printState(allPoints);

    // The flags have not changed. If I searh for the point in allPoints, then change the flag, it will change
    for(Point p : allPoints)
    {
        if(p.p == allPoints[0].prefs[2].p) allPoints[0].flag = false;


    }
    printState(allPoints);
}

void fillVectors(vector<Point> & allPoints)
{  

  pair<int,int> p1 = make_pair(0,0);
  pair<int,int> p2 = make_pair(5,0);
  pair<int,int> p3 = make_pair(3,7);
  pair<int,int> p4 = make_pair(2,9);
  vector<pair<int,int>> coords = {p1, p2, p3, p4};

    for(int i = 0; i < coords.size(); i++)
    {
        Point newPoint;        
        newPoint.p = coords[i];
        allPoints.push_back(newPoint);
    }

    // Fill the preference lists with every other point (in no particular order)
    for(int i = 0; i < allPoints.size(); i++)
    {
        for(int j = 0; j < allPoints.size(); j++)
        {
            if(i == j) continue; // Do not put a point in its own preference list
            allPoints[i].prefs.push_back(allPoints[j]);
        }

    }
}

void printState(vector<Point> & allPoints)
{        
    cout << "Contents of all points:\n";

    for(Point p : allPoints)
        cout << "point: (" << p.p.first << "," << p.p.second << ")" << "  Flagged? -> " << p.flag << "\n";
    cout << "~\nContents of each preference vector:\n";

    for(Point p : allPoints)
    {
        cout << "point: (" << p.p.first << "," << p.p.second << ")\tprefs: ";
        for(Point q : p.prefs)
            cout << "(" << q.p.first << "," << q.p.second << "), ";
       cout << "\n";

    }
     cout << "--------------------\n";
}

Здесь у меня есть все точки, которые содержат четыре пары.Функция состояния печати печатает каждую точку из всех точек вместе с ее флагом, а затем список предпочтений каждой точки.Мне нужно, чтобы вектор prefs в каждой точке содержал ссылки на этот точечный объект в векторе allPoints.Вместо этого он, кажется, просто делает копию.

Я хочу сделать это, чтобы я мог менять флаги точек за O (1), а не за O (n) время, необходимое для получения точки.из настроек, затем найдите его во всех точках и измените его

1 Ответ

0 голосов
/ 01 октября 2018

Если единственной частью состояния, которой вы хотите поделиться, является flag и если вы не планируете изменять значение элемента Point::p после создания объекта, вы можете заменить bool flag на std::shared_ptr<bool> flag и при копированиисозданы - shared_ptr будет скопировано и будет содержать значение, совместно используемое между объектами.

struct Point
{
    Point(const std::pair<int,int>& value)
        : p(value)
    {}

    Point(const Point&) = default;
    Point& operator = (const Point&) = default;

    const std::pair<int,int> p;
    vector<Point> prefs;
    std::shared_ptr<bool> flag = std::make_shared<bool>(true);
};

Тогда, если вы сделаете:

Point pt1({1,2});
auto pt2 = pt1;

std::cout << *pt2.flag << " ";
*pt1.flag = false;
std::cout << *pt2.flag << " ";

, на выходе будет "1 0«поскольку pt1 и pt2 объекты совместно используют один и тот же bool.

Примечание: если для Point::p нет const, то можно изменить его значение после создания копий из объекта - вв этом случае разделение flag для таких объектов не имеет смысла.

Конечно, это будет легко взломать, если все члены являются публичными, поэтому вам необходимо получить осторожный доступ к flag.Чтобы сделать этот код безопасным, следует использовать инкапсуляцию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...