The Java TreeNode class contains references to both children and parent. I see sometimes in C++ implementations, there are only left, right children pointers and no parent pointer.
In a C++ implementation, should there be a parent pointer?
This is really a matter of what you want to do with your tree. In many cases (think expression trees) you only really need to know about your children. If this is the case, then having a pointer to the parent is irrelevant. So look at what you need to do. If your child node needs to know information about the parent, then a parent pointer will be necessary, but in most cases it really isn't.
If you can give a few more details about what you're doing, I can probably give a better answer about if your problem would be improved by having a parent pointer.
Related
This answer writes a move constructor like this:
dumb_array(dumb_array&& other)
: dumb_array() // initialize via default constructor, C++11 only
{
swap(*this, other);
}
Note: this swap is a custom swap also defined on the class, not std::swap.
This answer suggests that use of std::move:
you should only call std::move where appropriate, but this is were personal preferences come in.
I just watched a Scott Meyers talk on move semantics where he stated that an rvalue reference as a function parameter is turned back into an lvalue by virtue of the fact that it is now named, and therefore std::move is necessary once again turn it back into an rvalue.
In other words, the code above may very well not be doing a move operation, and that, unlike the quote above, use of std::move in such contexts is not about personal preference but about actually gaining benefits of move semantics.
Is it accurate to say then that if std::move is not explicitly used inside a move constructor or a move assignment operator, moving is probably not actually happening, and instead a copy is being done?
Is it accurate to say then that if std::move is not explicitly used inside a move constructor or a move assignment operator, moving is probably not actually happening, and instead a copy is being done?
No, that is most certainly not accurate. In the particular case in the question, it fully depends on the implementation of swap.
A natural implementation would be swap(dumb_array&, dumb_array&) which internally swaps some pointers, perhaps like this:
void swap(dumb_array &lhs, dumb_array &rhs)
{
std::swap(lhs.pointer_to_data, rhs.pointer_to_data);
}
If that is the case, then the move constructor you've shown certainly performs a lightweight moveājust a pointer swap. Second, using std::move when calling swap would be downright wrong, as swap takes lvalue references.
I just watched a Scott Meyers talk on move semantics where he stated that an rvalue reference as a function parameter is turned back into an lvalue by virtue of the fact that it is now named, and therefore std::move is necessary once again turn it back into an rvalue.
That's correct.
But there are many misconceptions around this topic.
In other words, the code above may very well not be doing a move operation
It won't do a move. However, it's likely that swap is an efficient operation anyway and therefore you don't care.
use of std::move in such contexts is [...] about actually gaining benefits of move semantics.
Not true. Even if you use std::move, there is no guarantee that any moving will occur.
Is it accurate to say then that if std::move is not explicitly used inside a move constructor or a move assignment operator, moving is probably not actually happening, and instead a copy is being done?
moving can occur, even if there is no std::move.
So basically, std::move is neither necessary, nor sufficient, for moving to occur. This may seem quite surprising.
I think there is really no shortcut to this. If you want to understand this, find a good comprehensive tutorial. E.g. The popular C++ Rvalue References Explained by Thomas Becker.
Consider a frequently called recursive function having some parameters which do vary a lot among executions, and some which don't, representing some kind of a context information. For example, a tree traversal might look like this
private void Visit(Node node, List<Node> results)
{
if (IsMatch(node)) {
results.Add(node);
}
Visit(node.Left, results);
Visit(node.Right, results);
}
...
Visit(root, new List<Node>());
Obviously results collection is created once and the same reference used throughout all traversal calls.
The question is, does it matter for performance whether the function is declared as Visit(Node, List<Node>) or Visit(List<Node>, Node)? Is there a convention for the arguments order?
The vague idea is that fixed parameters might not be pushed in or popped out of stack constantly, improving the performance, but I'm not sure how feasible would that be.
I'm primarily interested in C# or Java, but would like to hear about any language for which the order matters.
Note: sometimes I happen to have three of four parameters overall. I realize that it is possible to create a class holding a context, or an anonymous function closing the context variables, but the question is about plain recursion.
This is going into the deepest conjecture territory for me, since there are an explosive number of variables that could affect the outcome ranging from the calling conventions of the platform to the characteristics of the compiler.
The question is, does it matter for performance whether the function
is declared as Visit(Node, List) or Visit(List, Node)? Is
there a convention for the arguments order?
In this kind of simple example, probably the most concise answer I can give is, "no unless proven otherwise" -- "innocent until proven guilty" sort of thing. It's highly unlikely.
But there are interesting scenarios that crop up in a more complex example like this:
API_EXPORT void f1(small a, small b, small c, small d, big e);
... vs:
API_EXPORT void f2(big a, small b, small c, small d, small e);
In this case, f1 might actually be more efficient than f2 in some cases.
It's because some calling conventions, like Win x64, allow the first four arguments passed to a function to be passed directly through registers without stack spills provided that they fit into a register and make up the first four parameters of the function.
In this case, with f1, the first four small arguments might fit into registers but the fifth one (regardless of size) needs to be spilled to the stack.
With f2, the first argument might be too big to fit into a register, so it needs to be spilled into the stack along with the fifth argument, so we could end up with twice as many variables being spilled to the stack and take a small performance hit (I've never actually measured a case like this, however).
This is a rare case scenario though even if it occurs, and it was critical for me to put that API_EXPORT specifier there because, unless this function is being exported, the compiler (or linker in some cases) can do all kinds of magic and inline the function and things of that sort and obliterate the need to pass arguments in this kind of precise way defined by its ABI.
In this kind of case, it might help a little bit to have parameters sorted in ascending order from smallest types that fit in registers to biggest types that don't.
But even then, is List<Node> a big type or a small type? Can it fit into a general-purpose register, e.g.? Languages like Java and C# treat everything referring to a UDT as a reference to garbage-collected memory. That might boil down to a simple memory address which does fit into a register. I don't know what goes on here under the hood, but I would suspect the reference itself can fit into a register and is actually a small type. A big type would be like a 4x4 matrix being passed by value (as a deep copy).
Anyway, this is all case-by-case and drawing upon a lot of conjecture, but these are potential factors that might sway things one way or another in some rare scenario.
Nevertheless, for the example you cited, I'd suggest a strong "no unless proven otherwise -- highly improbable".
I realize that it is possible to create a class holding a context, or
an anonymous function closing the context variables [...].
Often languages that provide classes generate machine instructions as though there is one extra implicit parameter in a function. For example:
class Foo
{
public:
void f();
};
... might translate to something analogical to:
void f(Foo* this);
It's worth keeping that in mind when it comes to thinking about calling conventions, aliasing, and how parameters are passed through registers and stack.
... but the question is about plain recursion
Recursion probably wouldn't affect this so much except that there might come a point where the compiler might cease to inline recursive functions, e.g. after a few levels, at which point we inevitably pay the full cost required of the ABI. But otherwise it's mostly the same: a function call is a function call whether it's recursive or not and the same concerns tend to apply for both. Potentially relevant things here most likely have much more to do with compiler and platform ABI than whether or not a function is being called recursively or non-recursively.
We have a pretty huge code base, sometimes with performance issues. Move semantics is not used at all. I am wondering how could I find places where move semantics might be useful. Do you have any experience how to localize such a places?
Since the standard containers have been updated to move elements whenever possible, a good place to start would be types that are stored (by value) in standard containers. If you make them MoveConstructible and MoveAssignable (and be sure to make the move operations noexcept where possible so e.g. std::vector will actually move not copy) then all code using containers of those elements can potentially benefit.
Other candidates are any non-trivial types that are passed to functions or returned from functions by value.
Of course another approach is the usual one for any performance issues: profile the code and find out what's slow. If it's due to lots of copying then consider if the copies can be avoided, and if not whether implementing move semantics might help. If the slowness isn't due to lots of copying then move semantics probably won't help.
Move construction is a great feature because once you add a move constructor you get all the performance benefit "for free". Sure, you can explicitly move objects, but many uses of the move constructor are actually implicit.
Some places (far from an exhaustive list) that benefit once you add a move constructor to a class would be:
std::vector<T> vec;
vec.push_back(T()); //implicit move into array
std::sort(vec.begin(), vec.end()); //may move if std::swap performs swap
T obj = foo(); //move construct if compiler doesn't apply RVO
T obj2 = obj + T(); //technically same as the line above
The great part about it is that once you add a move constructor to the class (usually only a few lines of code) you don't have to change ANY other code to start reaping the benefits of move!
Your biggest gains would most likely be in loops adding elements to containers, but you get an improvement in all of these areas just by adding a move constructor (which is often trivial to write).
However, 99% of the classes that will benefit from move are classes which allocate memory or resources, because move allows you to replace a deep copy with a shallow copy. Most other classes (such as classes that are just record types) don't gain anything from move.
I'm learning about ruby's mark and sweep approach to garbage collecting. I bumped into a few threads here and there (and this article via a SO thread which I can no longer spot), but they seemed to apply to older versions of ruby and a the information in them wasn't always consistent. (As things stand I'm getting the impression that it's mostly reference counting.)
Might anyone with some unrstanding of ruby 1.9.2's internals be around to chime in, on whether ruby knew how to handle the trickier back references and circular references? (Ideally with a few details/good pointers on how it's actually implemented.)
Mark-and-sweep GC, like almost every algorithm commonly labeled as garbage collection save reference counting, handles circular references just fine. This has nothing to do with the specific implementation. Regardless of the actual GC used by Ruby 1.9, it won't have trouble with cycles. Here's a sketch of the approach of mark-and-sweep collectors, but be assured that other collection schemes handle cyclic references just as well.
Mark all things known to be always reachable ("roots", basically everything that's directly in scope - global variables, local variables, etc.)
Mark all not-yet-marked objects referenced by marked objects
Repeat 2 until no references from marked to not-yet-marked objects remain
Enumerate all objects allocated, deallocates those not marked
You see, a circle of references that's reachable "from the outside" doesn't lead to infinite recursion (we don't visit a given object's references more than once) and a circle of references that isn't reachable isn't marked as reachable and thus freed (each element independently) after marking.
Does anyone know of a GC algorithm which utilises type information to allow incremental collection, optimised collection, parallel collection, or some other nice feature?
By type information, I mean real semantics. Let me give an example: suppose we have an OO style class with methods to maintain a list which hide the representation. When the object becomes unreachable, the collector can just run down the list deleting all the nodes. It knows they're all unreachable now, because of encapsulation. It also knows there's no need to do a general scan of the nodes for pointers, because it knows all the nodes are the same type.
Obviously, this is a special case and easily handled with destructors in C++. The real question is whether there is way to analyse types used in a program, and direct the collector to use the resulting information to advantage. I guess you'd call this a type directed garbage collector.
The idea of at least exploiting containers for garbage collection in some way is not new, though in Java, you cannot generally assume that a container holds the only reference to objects within it, so your approach will not work in that context.
Here are a couple of references. One is for leak detection, and the other (from my research group) is about improving cache locality.
http://ieeexplore.ieee.org/xpl/freeabs_all.jsp?arnumber=4814126
http://www.cs.umass.edu/~emery/pubs/06-06.pdf
You might want to visit Richard Jones's extensive garbage collection bibliography for more references, or ask the folks on gc-list.
I don't think it has anything to do with a specific algorithm.
When the GC computes the graph of objects relationship, the information that a Collection object is sole responsible for those elements of the list is implicitly present in the graph if the compiler was good enough to extract it.
Whatever the GC algorithm chosen: the information depends more on how the compiler/runtime will extract this information.
Also, I would avoid C and C++ with GC. Because of pointer arithmetic, aliasing and the possibility to point within an object (reference on a data member or in an array), it's incredibly hard to perform accurate garbage collection in these languages. They have not been crafted for it.