参考包装向量,push_back 失败?
vector of reference wrapper, push_back failure?
我有一个问题困扰着我;我的目标是创建一个八叉树。
实际上,它很便宜(但对于我想用那个八叉树做的事情来说已经足够了)。
我的问题是我的 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);
}
}
};
我真的不明白我做错了什么。
std::vector<std::reference_wrapper<Point>> datas;
某些东西必须拥有此向量所引用的对象。
您用对不再存在的对象的引用填充了向量。目前还不清楚为什么你认为你需要一个引用向量,但你不应该做一些不寻常的事情,除非你有一个很好的解释为什么正常的方式(一个值向量)不适合你。
我有一个问题困扰着我;我的目标是创建一个八叉树。
实际上,它很便宜(但对于我想用那个八叉树做的事情来说已经足够了)。
我的问题是我的 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);
}
}
};
我真的不明白我做错了什么。
std::vector<std::reference_wrapper<Point>> datas;
某些东西必须拥有此向量所引用的对象。
您用对不再存在的对象的引用填充了向量。目前还不清楚为什么你认为你需要一个引用向量,但你不应该做一些不寻常的事情,除非你有一个很好的解释为什么正常的方式(一个值向量)不适合你。