参考包装器的向量,push_back失败?

时间:2017-07-24 08:47:59

标签: c++ vector octree reference-wrapper

我有一个给我带来麻烦的问题;我的目标是创建一个八叉树。

实际上,它非常便宜(但对于我想要用的八叉树来说,它已经足够了。)

我的问题是我的std::vector<std::reference_wrapper<Point>>填充了相同的值。所以我的插入创建了一个无限循环。 但这是代码,也许它会更容易理解。我把评论放在发生错误的地方。

source.cpp

void main(){
    std::random_device rd;
    std::mt19937 rng(rd());
    std::uniform_real_distribution<double> uni(0, 2);
    auto random_integer = uni(rng);
    Point firstCenter = Point(1, 1, 1);
    Point firstHalfDimension = Point(1, 1, 1);
    Octree oct(firstCenter, firstHalfDimension);

    for (int i = 0; i < 3; ++i) {
        double x = uni(rng);
        double y = uni(rng);
        double z = uni(rng);
        Point ptmp = Point(x, y, z);
        std::cout << x << " " << y << " " << z << std::endl;
        auto po = std::ref(ptmp);
        oct.insert(po);
    }
}

Octree.hpp

class Octree {
    Node octree;
    Point firstCenter;
    Point firstHalfDimension;

public: 
    Octree() = default;
    Octree( Point& firstCenter, Point& firstHalfDimension) :
        firstCenter(firstCenter), firstHalfDimension(firstHalfDimension), octree(firstCenter, firstHalfDimension) {}

    void insert(std::reference_wrapper<Point> pt) {
        octree.insert(pt);
    }
};

Node.hpp(出现问题的地方)

#define MAXVAL 2
using Point = gmtl::Vec3d;

class Node {
    Point center;
    Point halfDimension;
    std::vector<std::reference_wrapper<Point>> datas;
    std::array<std::shared_ptr<Node>, 8> children;


    int getOctant(const std::reference_wrapper<Point> p) {
        int oct = 0;
        if (p.get()[0] >= center[0]) oct |= 4;
        if (p.get()[1] >= center[1]) oct |= 2;
        if (p.get()[2] >= center[2]) oct |= 1;
        return oct;
    }

    const bool isLeaf()  {
        return !children[0];
    }

public:

    Node(Point center, Point halfDimension) : center(center), halfDimension(halfDimension){
    }
    void insert(const std::reference_wrapper<Point> p) {
        if (isLeaf()){
            if (datas.size() == MAXVAL) { //Must subdivide
                std::cout << p.get()[0] << " " << p.get()[1] << " " << p.get()[2] << std::endl;
                for (int i = 0; i < datas.size(); ++i) {
                    std::cout << datas[i].get()[0] << " "
                        << datas[i].get()[1] << " "
                        << datas[i].get()[2] << std::endl;
 //The problem is here : the vector is filled with the same values, and it's the same value as p. let's say p = (0.4,0.7,0.8), then the for loop will show to the screen : 
 // 0.4 0.7 0.8
 // 0.4 0.7 0.8
 // 0.4 0.7 0.8
                }
                for (int i = 0; i < 8; ++i) {
                    Point newCenter;
                    newCenter[0] += halfDimension[0] * (i & 4 ? .5f : -.5f);
                    newCenter[1] += halfDimension[1] * (i & 2 ? .5f : -.5f);
                    newCenter[2] += halfDimension[2] * (i & 1 ? .5f : -.5f);
                    children[i] = std::make_shared<Node>(newCenter, halfDimension * .5);
                }
                int octant = getOctant(p);
                children[octant]->insert(p);
                for (int i = 0; i < datas.size(); ++i) {
                    int octant = getOctant(datas[i]);
                    children[octant]->insert(datas[i]);
                }


            }
            else { //Just add
                datas.push_back(p);
            }
        }
        else { //Non-leaf node
            children[getOctant(p)]->insert(p);
        }
    }
};

我真的不明白我做错了什么。

1 个答案:

答案 0 :(得分:2)

std::vector<std::reference_wrapper<Point>> datas;

必须拥有此向量包含引用的对象。

您使用对不再存在的对象的引用填充了向量。不清楚为什么你认为你需要一个引用的向量,但你不应该做一些不寻常的事情,除非你有一个非常好的解释为什么正常的方式(值的向量)赢了&t为你工作。