I had two matching vectors of unique_ptr. I decided to unify them by making one vector of structs containing two unique_ptr (the struct will also contain other items, eventually, hence this refactoring).
What is the best approach for me to add new items in this vector?
My current code is
std::vector<DestinationObjects> destinations;
for (unsigned short &id: ids) {
DestinationObjects d;
d.transmitter = unique_ptr<Transmitter> (new Transmitter(id));
d.controller = unique_ptr<Controller> (new Controller(id));
destinations.push_back(d);
}
Of course this copies d, causing issues with unique_ptr. What is the best approach to fixing this?
Options I can conceive of, some of which I am not sure will work:
Just switch to shared_ptr. (A simple find-replace, but feels like a cop-out).
Write a move constructor for the struct that moves the unique_ptr. (Another thing to maintain that could go wrong, as I expand the struct).
Push back an empty struct instance with null pointers for the unique_ptr and edit these in place once in the vector. (Fiddly syntax. Also I'm not sure this would even work).
Any ideas what would be another approach? Or why I should prefer one of the ones I have listed?
Simpley do a vec.emplace_back( std::move(d) ).
If (as mentioned in your comment) your compiler does not implement implicit move construtors, write your own move constructor. My advice in the future is whenever you have a problem with any C++11 feature and are asking a question, mention that you are using this compiler, as there is a pretty good chance that it's "C++11 support" will be an important issue.
If your compiler does not support any move constructor at all, stop using unique_ptr -- they are rather useless without move constructors. ;)
Related
Let me refer to the following example from the boost spirit tutorial about parsing
a "mini XML" data structure. My question doesn't actually have anything to do with
spirit, it's really about boost::variant, and making efficient "recursive" variant
structures.
Here's the code:
struct mini_xml;
typedef
boost::variant<
boost::recursive_wrapper<mini_xml>
, std::string
>
mini_xml_node;
struct mini_xml
{
std::string name; // tag name
std::vector<mini_xml_node> children; // children
};
In the tutorial, they go on to show how to "adapt" the struct mini_xml for boost::fusion,
and then write spirit grammars that load data into it.
However, it occurred to me recently that there's a subtle issue in this example that may lead to significant overhead.
The issue is that the variant type, mini_xml_node, is not no-throw move constructible in this example. The reason is that it contains boost::recursive_wrapper. The recursive_wrapper<T>
always represents a heap-allocated instance of T, and it does not have an empty state. When a
variant containing recursive_wrapper is moved from, a new dynamic allocation is made and a new T
is move constructed from the old T -- we can't simply take ownership of the old T, because that would leave the old variant in an empty state. (I only looked into this after I was trying to implement my own variant type -- this is indeed what boost::variant does afaict, and it is indeed not no-throw move constructible in this example.)
Because mini_xml_node is not no-throw move constructible, the container std::vector<mini_xml_node> children will be on the "slow path" -- when it uses std::move_if_noexcept, it will elect to copy the elements rather
than move them. This happens for instance every time the vector capacity increases. And when we copy a mini_xml_node, we copy all of its children.
So for instance, if I want to parse from disk an xml tree which has depth d and branching factor b, I estimate that we will end up copying each leaf of the tree about d * log b times, since pushing back into a vector b times causes reallocation about log b times, and it will happen for each ancestor of the leaf.
I don't have an actual application right now where I care about this overhead, but it's easy for me to imagine that
I might. For instance I might want to write a high-performance parser using spirit for some small utility program
that will check that e.g. a data file has a certain form, or count some statistic of it or something. And then it
might very well be that the time to parse dominates the overall runtime of the utility, so these copies might be performance critical.
The question is, what is the simplest and cleanest way to change the code to prevent these copies from happening? I thought of a few approaches
but maybe you see a better way.
Quick and dirty: Write a wrapper class that contains a mini_xml_node but the move constructor is explicitly marked
noexcept, even though it isn't really noexcept. This will cause termination if an exception is thrown, but that should be pretty rare...
Use an alternative to std::vector that doesn't use std::move_if_noexcept, and instead just uses move. If I understand right, boost::vector does this. The tradeoff is it doesn't have strong exception safety, but it's not clear if that's really a problem here.
(This one doesn't actually work.) Add boost::blank as one of the options for mini_xml_node.
When blank is one of the value types, boost::variant has special code that adapts its behavior -- it will use
blank as a natural empty state when default constructing and when making type-changing assignments.
However, it appears that putting blank into boost::variant doesn't go so far as allowing me to no-throw move construct
the variant even though it contains a boost::recursive_wrapper type. Tested on coliru with boost 1.63:
http://coliru.stacked-crooked.com/a/87620e443470b70c
(Maybe this would be a useful feature for boost::variant in the future? What I'd like is that the move constructor transfers ownership of the recursively-wrapped guy, and puts the old variant in the blank state, and marks the move constructor as noexcept.)
I have a class that represents a runtime context and builds a tree, the tree root is held in a unique_ptr. When building the tree is done I want to extract the tree. This is how it looks (not runnable, this is not a debugging question):
class Context {
private:
std::unique_ptr<Node> root{new Node{}};
public:
// imagine a constructor, attributes and methods to build a tree
std::unique_ptr<Node> extractTree() {
return std::move(this->root);
}
};
So I used std::move() to extract the root node from the Context instance.
However there are alternatives to using std::move() e.g.:
std::unique_ptr<Node> extractTree() {
// This seems less intuitive to me
return std::unique_ptr<Node>{this->root.release()};
}
Is std::move() the best choice?
You should definitely go with the first version as the second one basically does the everything the first version does with more code and less readability.
Philosophically speaking, the second version moves the unique pointer, no more, no less. so why going around the table instead of using the already existing, more readable and more idiomatic std::unique_ptr(std::unique_ptr&&) ?
And lastly, if your smart pointer somewhere in the future will hold custom deleter , the first version will make sure the deleter moves as well, the second version does not moves the deleter. I can definitely imagine a programmer building non-custom deleter unique pointer out of custom-deleter unique_pointer with using release. With move semantics, the program will fail to compile.
What you're doing is dangerous. Once you've called getTree(), you must not call it a second time, which is not clear from the interface. You may want to reconsider your design (e.g. a shared_ptr might do a better job, or simply store the root as a raw pointer and manually take care of the deallocation).
Anyway, using std::move is the better option of the two if you want to stick with your design as it makes your intent more clear.
EDIT: apparently 'must not' has a special meaning of forbideness in English I was not aware of. It is fine to call the function twice or as many times as you want, but will not return a pointer to a valid object if done consecutively.
So after working on my last question, I boiled it down to this:
I need to add an unknown number user-defined classes (object_c) to a boost::intrusive::list. The classes have const members in them. All I need to do to push them to the list is to construct them and then have them persist, they automatically add themselves.
The code in question is basically
for (unsigned i = 0; i < json_objects.count(); ++i) {
ctor_data = read(json_objects[i]);
// construct object here
}
What I've tried:
mallocing an array of objects, then filling them in: Doesn't work, because I have const members.
static object_c *json_input = (object_c*) malloc(json_objects.size() * sizeof(object_c));
...
json_input[i](ctor_data); //error: no match for call to (object_c) (ctor_data&)
Making a pointer: This doesn't work, functions don't work properly with it, and it doesn't get destructed
new object_c(ctor_data);
Pushing the object back to an std::vector: This doesn't work, boost rants for dozens of lines when I try (output here)
vector_of_objects.push_back(object_c(ctor_data));
Just declaring the darn thing: Obviously doesn't work, goes out of scope immediately (dur)
object_c(ctor_data);
I'm sure there is an easy way to do this. Anyone have any ideas? I've been at this problem for most of the weekend.
#3 should be the method you need to use. You need to elabourate on what your errors are.
If it is just operator= as you show in your previous question, and you dont want to define one, you can try emplace_back as long as you are in C++11. Of Course I am talking std::vector, I need to check what is the equivalent if any in boost::intrusive. Edit: I might be wrong, but it doesnt seem to support move semantics yet..
Alternatively use #2 with smart pointers.
If you are going with #1, you would need to use placement new as #rasmus indicates.
At the end of the documentation's usage section it tells you that
“The lifetime of a stored object is not bound to or managed by the container”
So you need to somehow manage the objects’ lifetime.
One way is to have them in a std::vector, as in the documentation’s final example.
Sorry for the late reply, exam studying and all that.
It was simpler than I was making it out to be, basically. Also, for this answer, I'm referring to my class as entity_c, so that an object of entity_c actually makes sense.
What I was doing in my OP was when I push_back'd an entity_c, it was automatically adding itself to a global intrusive::list, and somehow that made it not work. After I stopped being lazy, I wrote up a minimal compilable progam and played around with that. I found out that making an std::vector to store the constructed entity_cs in worked (even though it deconstructs them when they're added? I dunno what that's about). Then all I had to do was populate a local intrusive::list with those objects, then clone the local list into the global list.
Thanks for all the help, I'll tweak that program to try and fit in different stuff, like placement new suggested by #rasmus (thanks for that, hadn't seen that before). Also thanks to #karathik for showing my emplace_new, I think I might have to go and find out about all these new C++11 features that have been added in, there are so many cool ones. I even learnt how to make my own copy constructor.
Truly and edifying educational experience.
Learning C++, so be gentle :)...
I have been designing my application primarily using heap variables (coming from C), so I've designed structures like this:
QList<Criteria*> _Criteria;
// ...
Criteria *c = new Criteria(....);
_Criteria.append(c);
All through my program, I'm passing pointers to specific Criteria, or often the list. So, I have a function declared like this:
QList<Criteria*> Decision::addCriteria(int row,QString cname,QString ctype);
Criteria * Decision::getCriteria(int row,int col)
which inserts a Criteria into a list, and returns the list so my GUI can display it.
I'm wondering if I should have used references, somehow. Since I'm always wanting that exact Criteria back, should I have done:
QList<Criteria> _Criteria;
// ....
Criteria c(....);
_Criteria.append(c);
...
QList<Criteria>& Decision::addCriteria(int row,QString cname,QString ctype);
Criteria& Decision::getCriteria(int row,int col)
(not sure if the latter line is syntactically correct yet, but you get the drift).
All these items are specific, quasi-global items that are the core of my program.
So, the question is this: I can certainly allocate/free all my memory w/o an issue in the method I'm using now, but is there are more C++ way? Would references have been a better choice (it's not too late to change on my side).
TIA
Mike
I would return QList<Criteria> as a plain value. QList is one of Qt's shared classes, meaning that its internal representation is shared between multiple instances so long as none of them are modified.
If the Criteria class is fairly complex, such that an incidental copy made because one of the lists is modified at some point incurs noticable overhead, then I would use QSharedData in the implementation of Criteria so that it, too, is only copied as needed.
This approach has two downsides: one, the copying, if any, is implicit and may happen when you don't expect it to, and two, it doesn't allow for polymorphic use of Criteria. If you have Criteria as the root of a class hierarchy, then you must use pointers. In that case, I would use shared_ptr from Boost or C++ TR1 to avoid memory management hassles, or make Critera inherit publicly from QObject and make all Critera objects children of Decision.
I don't think references would be a better choice. If you are dynamically allocating these objects, you still need keep a copy of the pointer around to delete later. Plus, when passing around pointers you don't have to worry about copy constructors or an implicit sharing technique like QSharedData. You'll still get "that exact Criteria back".
My advice is: Unless you have a really good reason to make things more complex, keep it simple.
However, from a Qt standpoint you should generally not pass around pointers or references to Qt objects. These objects do use implicit sharing so they don't act like "normal" C++ objects. If you are still learning C++ I'd suggest leaving this technique out of your own code for now. But to use Qt effectively you need to understand how it works so I recommend reading more about it here:
http://qt.nokia.com/doc/4.6/implicit-sharing.html
Good luck!
EDIT:
One thing I forgot to mention. If you know you don't want you class to be copied, you can enforce this by declaring a private copy constructor and operator= overload:
class A
{
//Code goes here
private:
A(const A&);
A& operator=(const A&);
};
I want to be able to have a vector of vectors of some type such as:
vector<vector<MyStruct> > vecOfVec;
I then create a vector of MyStruct, and populate it.
vector<MyStruct> someStructs;
// Populate it with data
Then finally add someStructs to vecOfVec;
vecOfVec.push_back(someStructs);
What I want to do is avoid having the copy constructor calls when pushing the vector. I know this can be accomplished by using a vector of pointers, but I'd like to avoid that if possible.
One strategy I've thought of seems to work, but I don't know if I'm over-engineering this problem.
// Push back an empty vector
vecOfVec.push_back(vector<MyStruct>());
// Swap the empty with the filled vector (constant time)
vecOfVec.back().swap(someStructs);
This seems like it would add my vector without having to do any copies, but this seems like something a compiler would already be doing during optimization.
Do you think this is a good strategy?
Edit: Simplified my swap statement due to some suggestions.
The swap trick is as good as it gets with C++03. In C++0x, you'll be able to use the vector's move constructor via std::move to achieve the same thing in a more obvious way.
Another option is to not create a separate vector<MyStruct>, but instead have the code that creates it accept it a a vector<MyStruct>& argument, and operate on it. Then, you add a new empty element to your outer vector<vector<MyStruct>>, and pass a reference to the code that will fill it.
I know this can be accomplished by
using a vector of pointers, but I'd
like to avoid that if possible.
Why?
That would be the most intuitive/readable/maintainable solution and would be much better than any weird hacks anyone comes up with (such as the swap you show).
Tim,
There's a common pattern to solve this. This is called smart pointers, and the best one to use is boost::shared_ptr.
Then, never pass vector by value or store it. Instead, store boost::shared_ptr >. You don't need to care about allocations/deallocations (when the containing vector is destroyed, so will be the others, just as in your code), and you can access the inner members almost the same way. The copy is, however, avoided by means of the smart pointer object's reference counting mechanism.
Let me show you how.
using boost::shared_ptr;
vector<shared_ptr<vector<MyStruct> > vecOfVecs;
shared_ptr<vector<MyStruct> > someStructs(new vector<MyStruct>);
// fill in the vector MyStructs
MyStructs->push_back(some struct.... as you usually do).
//...
vecOfVecs.push_back(someStructs); // Look! No copy!
If you do not already use boost::shared_ptr, I recommend downloading it from boost.org rather than implementing your own. It is really irreplaceable tool, soon to be in the C++ standard library.
You can either do something like vect.push_back(vector<MyStruct>()); and do vect.back().push_back(MyStruct()); or use smart pointers and have a vector of smart pointers to vector<MyStruct>
I think the swap idea is already fine, but can be written much easier:
vecOfVec.push_back(vector<MyStruct>());
vecOfVec.back().swap(someStructs);