Ancestor readAncestor(ifstream & fin)
{
// Reads the data and creates an ancestor
return Ancestor;
}
This will mean I'm returning byVal. I will be calling this function inside of a while loop reading it hundreds of times. My question is whether creating a copy could be pretty time consuming? Is returning byVal classes generally a bad thing?
Would it be much better if I did this?
1 2 3 4 5 6
Ancestor readAncestor(ifstream & fin, Ancestor & currentAncestor)
{
// Reads the data and creates an ancestor
return currentAncestor;
}
I apologize if this is a technical and dumb question. But it seems like
return byVals of classes can be pretty time consuming and should be avoided.
What do you think?
You generally don't want to do this. Instead, you would pass a reference or pointer to readAncestor that would then hold the new Ancestor. No copy needed.
tl;dr it won't be time consuming, but I'd recommend passing by reference because it is arguably cleaner.
Returning by value is perfectly fine. I imagine somewhere in your code you would have the line:
ancestor = readAncestor(ifs); //might be ancestors[i] if you're using an array or something
Inside readAcenstor, you're going to construct (a.k.a. make) a struct and then when that function returns, you're going to assign the Ancestor you made to ancestor/ancestors[i]. The thing is, construction and assignment take constant time, meaning you won't see a performance difference versus passing by reference. You'd still need to construct the Ancestor you pass to the function before although you'd probably have one less assignment statement, but then again, assignment takes constant time which means it doesn't really play a role. Also, if we're speaking of only a hundred or so iterations in your loop, then any negligible effect wouldn't be noticeable.
Also, your second implementation (passing by reference) means your function doesn't need to return an object. When you modify the currentAncestor object, you are modifying to object passed directly. No need to return it.
> Is returning byVal classes generally a bad thing?
No. It is a good thing.
> But it seems like return byVals of classes can be pretty time consuming and should be avoided.
No. Unless the object is not moveable and/or copying an object has observable side effects.
In general, favour value semantics over reference semantics (for more than one reason.)
Where performance is a concern, one measurement is worth a thousand opinions.
[ 0.000000] Detected 2200.088 MHz processor.
Linux stacked-crooked 3.2.0-74-virtual #109-Ubuntu SMP Tue Dec 9 17:04:48 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
===========
clang version 3.6.0 (tags/RELEASE_360/final 235480)
use pass by reference everywhere: 2.46 seconds.
use value semantics everywhere: 2.54 seconds.
===========
g++ (GCC) 5.2.0
use pass by reference everywhere: 2.52 seconds.
use value semantics everywhere: 1.42 seconds.
This will mean I'm returning byVal. I will be calling this function inside of a while loop reading it hundreds of times. My question is whether creating a copy could be pretty time consuming?
No it is not.
As long as there is no second branch where the function might end there is something called return-value-optimization.
That means that the Object you're returning is basically created wherever the output is.
The thing is, construction and assignment take constant time, meaning you won't see a performance difference versus passing by reference.
Does that mean that, no matter how much data you have in a class, (AKA 5 strings or 10 strings), it would take the same amount of time? Intuitively, I thought 10 strings would take longer.
It means that you should not be stressing yourself out over unobservable inefficiencies. Yes, copying 10 stings technically takes more CPU cycles, but when that time difference is measured in picoseconds can you honestly say that you give a damn?
Rounding error, thermal issue, variance in voltage, inductance, derating, communism, gay marriage, it could be anything. Chunks of silicon aren't exactly ideal mechanisms for generating constant frequencies, that's why the SI standard doesn't use it.
Rounding error, thermal issue, variance in voltage, inductance, derating,
but yeah, I'd accept it if it was a wall-clock but when measuring the CPU cycles the number should stay constant because you need the same amount of CPU cycles every time, right?
Not necessarily, your CPU can change it's frequency for any number of reasons. In fact depending on the power settings your CPU may cut its frequency in half to save power on a laptop when the charger is unplugged. How much of a variance are you getting? Mine is only a few thousandths of a second.
How much of a variance are you getting? Mine is only a few thousandths of a second.
yeah, something like that but sometimes even a bit more than one hundredth; but well, it's nothing to be concerned about when running it a million times :)
Does that mean that, no matter how much data you have in a class, (AKA 5 strings or 10 strings), it would take the same amount of time? Intuitively, I thought 10 strings would take longer.
You're right. It would take longer, but that's because they'd be two different classes, and I was speaking more abstractly than anything. If you have a particular class (whatever its data structure may be), it takes c time to construct; a different class may take a different amount of time to construct. The point is that because construction time is constant, the timing of whatever you're trying to do with the class won't be affected by construction.
Now if I may dive a bit deeper down the computer science rabbit hole: This is a generalization, but it's a safe one to make. Some objects do not take constant time. If memory serves me correct, construction of string takes time proportional to the length of the string for example, but regardless, it is so insignificant for most projects that one shouldn't even concern themselves with it. Issues with such low-level performance only arise when you're working with millions or billions of objects, and there is some pressure to do some action as fast as possible.