i work on graphics applications , have been using shared & unique pointers because handles memory deallocation me (aka convenience) bad (if that's reason why use them).
i read answer question on stackoverflow mentioned according b. stroustrup, unique/shared ptrs should not used , arguments should passed value instead.
i have case in graphics think using shared_ptr makes sense i'd know experts (i not c++ experts) if on doing/thinking , if doing instead (to conform c++ recommendations , efficiency)
i take general problem occurs in rendering/ray-tracing. in particular problem have pool of objects (we use triangles explanation) , structure simplicity of explanation refer regular 3d grid. let's @ point need insert triangles grid: means need check of bounding volume of each inserted triangle overlaps of cells grid, , does, each overlapped cell needs keep pointer/reference triangle (for later use). triangle may overlap more 1 cell, can referenced multiples times several cells (you see going shared_ptr
here).
note outside of grid structure, don't need pool of triangles (so technically object owns pool of triangle here, grid or more precisely grid's cells).
class grid { struct cell { std::vector<std::shared_ptr<const triangle>> trilist; }; void insert(triangle*& tri_) { std::shared_ptr<const triangle> tri = tri_; (each cell overlapped tri) { // compute cell index uint32_t = ... cells[i].trilist.push_back(tri); } } cell cells[res * res * res]; }; void createpooloftrianglesandinsertintogrid() { grid grid; uint32_t maxtris = 32; triangle* tris = new triangles[maxtris]; // process triangles ... // insert grid (uint32_t = 0; < maxtris; ++i) { // use placement new triangle* tri = new (&tris[i]) triangle; grid.insert(tri); } // no need delete tris here ... should done // grid when go out of function's scope }
it sounds complicated motivation behind design follow stroustrup's recommendation. in case function createpooloftrianglesandinsertintogrid
doesn't owned triangles, it's cells of grid do. allocate memory in function createpooloftrianglesandinsertintogrid
because need create triangles, , use placement new method pointer each triangle in pool can pass grid insert
method (i defer memory management of object method). in there, converts triangle shared_ptr
, cells can share "reference" (using shared_ptr
).
i wanted know if opinion going in right direction, or if appears wrong, both in terms of implementation , in terms of possible loss of efficiency (i allocate pool of memory, use new placement create temp triangle, pass on grid insert method, convert shared_ptr, ...)
i trying both learn, , improve code , hope can provide valuable professional feedback.
edit: trying find right approach problem + try provide later modifications based on comments
it looks me grid
owns triangles. assuming triangles relatively light (3-5 dimensions?).
i think might suit. using container in grid
take ownership of triangles by value. container delete triangles when grid
goes out of scope.
then each cell
uses raw pointers keep track of triangles references. cell
s don't own triangles hold pointers triangles owned grid
.
class grid { struct cell { std::vector<triangle*> trilist; // non owning }; void insert(triangle tri) // pass value { tris.push_back(tri); // grid owns value for(each cell overlapped tri) { // compute cell index uint32_t = ... cells[i].trilist.push_back(&tris.back()); } } // use deque because won't re-allocate when adding // new elements end std::deque<triangle> tris; // elements owned value cell cells[res * res * res]; // point owned elements }; void createpooloftrianglesandinsertintogrid() { grid grid; // owns triangles (by value) uint32_t maxtris = 32; std::vector<triangle> tris(maxtris); // process triangles // ... // insert grid for(auto tri: tris) grid.insert(tri); } // no need delete tris here ... should done // grid when go out of function's scope }
note: use std::deque
store triangles value in grid
. that's because won't ever reallocate internal memory when adding new triangles. if used std::vector
here raw pointers end dangling when std::vector
resized itself.
alternatively:
given looks build triangles in function , pass of them grid
, why 1 @ time? pass whole container in in 1 go. if using move semantics won't have copy anything:
class grid { struct cell { std::vector<triangle*> trilist; // non owning }; // accept entire container in-tack // (no reallocations allowed after point) void insert(std::vector<triangle> tris) // pass value (able move in) { // for(auto& tri: tris) { for(each cell overlapped tri) { // compute cell index uint32_t = ... cells[i].trilist.push_back(&tri); } } } // using vector must not resized after // cells have been pointed elements!!! std::vector<triangle> tris; // elements owned value cell cells[res * res * res]; // point owned elements }; void createpooloftrianglesandinsertintogrid() { grid grid; // owns triangles (by value) uint32_t maxtris = 32; // build triangles std::vector<triangle> tris(maxtris); // process triangles // ... // insert grid grid.insert(std::move(tris)); // move whole darn container (very efficient) // no need delete tris here ... should done // grid when go out of function's scope }
note: used std::vector
because not adding triangles 1 one after arrive in grid
. must make sure inside grid
owning `std::vector not resized.
Comments
Post a Comment