What is the best way to put large objects on the heap?
bigdata, c++, c++11, heap-memory
Solution
Give `Node` a move constructor and move assignment operator (to make operations on the set cheap), then use a mix of option 1 and 2. `std::set` will already be heap allocating its contents so you don't need to worry about allocating a `RoadMap` on the heap. Note the extra `std::move` inside `addNode` to allow `Node`s to be moved into the set.
class RoadMap
{
set<Node> allNodes;
void addNode (Node node)
{
allNodes.emplace(std::move(node));
}
};
int main()
{
RoadMap map;
// open file etc.
for (const auto& nodeData : nodesInFile)
{
map.addNode(Node(nodeData));
}
}
Problem
I am working on a project that needs to load many objects from a data file and store them in memory. Since I have been told that stack space is rare and larger amounts of data should be on the heap I put everything on the heap. However, my impression is that I overdid it a little bit. My current design looks like this: ``` class RoadMap { unique_ptr<set<unique_ptr<Node>>> allNodes; void addNode(unique_ptr<Node> node) { this->allNodes->insert(std::move(node)); } } int main() { unique_ptr<RoadMap> map(new RoadMap()); // open file etc. for (auto nodeData : nodesInFile) { map->addNode(unique_ptr<Node>(new Node(nodeData))); } } ``` From what I understand by now, this creates a lot of overhead because there are many unique pointers involved that I think I do not need. If I understand correctly, it should be sufficient to only have one unique pointer barrier in the "pointer chain". However, I am unsure what the best practice is to do this. Option 1 ``` class RoadMap { unique_ptr<set<Node>> allNodes; void addNode (Node node) { this->allNodes->insert(node); } } int main() { RoadMap map; //open file etc. for (auto nodeData : nodesInFile) { map.addNode(Node(nodeData)); } } ``` The advantage of this seems to me that the `RoadMap` class itself is the only one that needs to take care of heap allocation and does so only once when creating the `set`. Option 2 ``` class RoadMap { set<Node> allNodes; void addNode (Node node) { this->allNodes.insert(node); } } int main() { unique_ptr<RoadMap> map(new RoadMap()); // open file etc. for (auto nodeData : nodesInFile) { map->addNode(Node(nodeData)); } } ``` Here the unique pointer is only in the main function meaning that the users of the `RoadMap` class will need to know that this object can become quite large and should be put on the stack. I don't think that this is an overly nice solution. Option 3 ``` class RoadMap { set<unique_ptr<Node>> allNodes; void addNode(unique_ptr<Node> node) { this->allNodes.insert(std::move(node)); { } int main() { RoadMap map; // open file etc. for (auto nodeData : nodesInFile) { map.addNode(unique_ptr<Node>(new Node(nodeData))); } } ``` This solution uses many unique pointers which means that when deleting the `RoadMap` many destructors and `delete`s will need to be called. Also the `RoadMap` caller has to supply a `unique_ptr` when adding a node meaning that he has to do the heap allocation himself. Right now, I am favouring option 1 over the others. However, I have only been coding C++ for a comparatively short time and am unsure whether I fully understand the concepts behind memory management which is why I want you to (in)validate my opinion. Am I correct in assuming that option 1 is the best way to do this? Do you have any additional references to best practices for this sort of thing?