用对另一个矢量的引用填充一个矢量

时间:2018-10-01 19:43:40

标签: c++ vector

我有一个表示点(allPoints)的结构向量。此向量包含给定平面上的所有点集合(在此示例中,它包含四个点)。每个结构都包含一对表示一个点,一个标志的整数,以及另一个包含平面上其他所有点的点向量。

我想要做的是从一个点的首选项列表中选择一个点,更改其标志,并将此更改应用于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";
}

在这里,我的allPoints拥有四对。打印状态功能将打印所有点中的每个点及其标志,然后打印每个点的首选项列表。我需要的是每个点的prefs向量在allPoints向量中保存对该点对象的引用。相反,它似乎只是在复制。

我想这样做,以便可以在O(1)时间更改点标志,而不是从首选项中获取点所需的O(n)时间,然后在allPoints中搜索并更改它< / p>

1 个答案:

答案 0 :(得分:0)

如果您要共享的状态的唯一部分是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 << " ";

由于pt1pt2对象共享相同的bool,因此输出将为“ 1 0”。

注意:如果const中没有Point::p,则可以在创建对象的副本后更改其值-在这种情况下,共享此类对象的flag是没有意义的。

当然,鉴于所有成员都是公开的,这很容易打破,因此您需要仔细访问flag。为了使此代码安全-应该使用封装。