我希望有一个类,它使用boost::geometry::index::rtree
作为空间索引器。这个类本身应该知道boost,所以我使用这样的东西:
struct VeryImportantInfo
{
...
float x;
float y;
}
class Catalogue
{
...
public:
std::vector<std::shared_ptr<VeryImportantInfo> > FindIn(float x1, float x2, float y1, float y2);
protected:
using point = bg::model::point<float, 2, bg::cs::cartesian>;
using value = std::pair<point, std::shared_ptr<VeryImportantInfo> >;
using box = bg::model::box<point>;
boost::geometry::index::rtree< value, bgi::quadratic<16> > rtree;
}
std::vector<std::shared_ptr<VeryImportantInfo> > Catalogue::FindIn(float x1, float y1, float x2, float y2)
{
box query_box(point(x1, y1), point(x2, y2));
???
}
我不知道如何正确地进行查询(请不要通过副本查看这个糟糕的矢量返回,这只是为了清酒)。我可以这样做:
std::vector<std::shared_ptr<VeryImportantInfo> > Catalogue::FindIn(float x1, float y1, float x2, float y2)
{
box query_box(point(x1, y1), point(x2, y2));
std::vector<value> result_s;
rtree.query(bgi::intersects(query_box), std::back_inserter(result_s));
std::vector<std::shared_ptr<VeryImportantInfo> > results;
results.reserve(result_s.size());
for( auto& p : result_s)
{
results.emplace_back(p.second);
}
return results;
}
我想知道,我怎样才能摆脱内部副本(不返回副本,results.emplace_back(p.second);
- 这个)。因为result_s
我可以获得10k以上的结果,这将是一种浪费。
谢谢!
答案 0 :(得分:2)
更新到评论
如果首先担心临时矢量,请不要使用。您可以使用qbegin()
中的qend()
/ boost::geometry::index
免费功能:
std::vector<std::shared_ptr<VeryImportantInfo> > Catalogue::FindIn(float x1, float y1, float x2, float y2)
{
box query_box(point(x1, y1), point(x2, y2));
auto b = bgi::qbegin(rtree, bgi::intersects(query_box)),
e = bgi::qend(rtree);
auto range = boost::make_iterator_range(b, e);
using namespace boost::adaptors;
return boost::copy_range<std::vector<std::shared_ptr<VeryImportantInfo>>>(
range | transformed([](value const& p) { return p.second; }));
}
事实上,如果知道rtree是常数,你甚至可以直接返回惰性范围,甚至不分配单个向量。
原始/旧答案文字如下:
如果没有引用计数,则无法复制共享指针。
当然,您可以将value
对更改为包含引用到shared_ptr,但您可以使用原始引用(std :: reference_wrapper)或{{1 }}
weak_ptr
以下是我对原始引用的看法(只保留重要数据):)
<强> Live On Coliru 强>
std::reference_wrapper<T>
#include <iostream>
#include <vector>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/index/rtree.hpp>
namespace bg = boost::geometry;
namespace bgi = bg::index;
struct VeryImportantInfo {
float x;
float y;
};
VeryImportantInfo a = { 2, 2 };
VeryImportantInfo b = { 3, 3 };
VeryImportantInfo c = { 4, 4 };
class Catalogue
{
public:
Catalogue() {
rtree.insert(value(point(a.x, a.y), a));
rtree.insert(value(point(b.x, b.y), b));
rtree.insert(value(point(c.x, c.y), c));
}
std::vector<std::reference_wrapper<VeryImportantInfo> > FindIn(float x1, float x2, float y1, float y2);
protected:
using point = bg::model::point<float, 2, bg::cs::cartesian>;
using value = std::pair<point, std::reference_wrapper<VeryImportantInfo> >;
using box = bg::model::box<point>;
boost::geometry::index::rtree< value, bgi::quadratic<16> > rtree;
};
std::vector<std::reference_wrapper<VeryImportantInfo> > Catalogue::FindIn(float x1, float y1, float x2, float y2)
{
box query_box(point(x1, y1), point(x2, y2));
std::vector<value> result_s;
rtree.query(bgi::intersects(query_box), std::back_inserter(result_s));
std::vector<std::reference_wrapper<VeryImportantInfo> > results;
results.reserve(result_s.size());
for(auto& p : result_s) {
results.push_back(p.second);
}
return results;
}
int main() {
Catalogue cat;
for (VeryImportantInfo& vii : cat.FindIn(1,2,3,4))
std::cout << vii.x << ", " << vii.y << "\n";
}
这与std::weak_ptr<T>
相同。有人可能会说这并没有解决太多问题(因为重新计算仍在进行中),但至少需要减少工作量。
<强> Live On Coliru 强>
weak_ptr<>