评论更新:
如果一开始的担心是关于临时向量的,那么就不要使用它。你可以使用boost::geometry::index
中的qbegin()
/ qend()
自由函数:
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是常量,甚至可以直接返回lazy range而不分配单个向量。
原始/旧答案文本如下:
您无法在没有引用计数的情况下复制共享指针。
当然,您可以将value
对更改为包含对shared_ptr的引用,但是您可以使用原始引用(std::reference_wrapper)或weak_ptr
。
std::reference_wrapper<T>
这是我使用原始引用的方式(只需保留您的重要数据即可:)):
在Coliru上实时查看
#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>
这里介绍的是使用weak_ptr<>
的相同内容。有人可能会认为这并没有解决太多问题(因为引用计数仍在发生),但至少需要的工作量更少了。
在 Coliru 上查看实例
#include <iostream>
#include <memory>
#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;
};
auto a = std::make_shared<VeryImportantInfo>(VeryImportantInfo{2, 2});
auto b = std::make_shared<VeryImportantInfo>(VeryImportantInfo{3, 3});
auto c = std::make_shared<VeryImportantInfo>(VeryImportantInfo{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::weak_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::weak_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::weak_ptr<VeryImportantInfo> > results;
results.reserve(result_s.size());
for(auto& p : result_s) {
results.push_back(p.second);
}
return results;
}
int main() {
Catalogue cat;
for (auto& vii_p : cat.FindIn(1,2,3,4))
if (auto vii = vii_p.lock())
std::cout << vii->x << ", " << vii->y << "\n";
}
result_s
向量中拥有 >10k 个对象,因此这不是引用计数的问题,整个数组的复制将是一种巨大的浪费。 - DoctorMoishamap_values
范围适配器。 - sehe