LemonDrop
"[@NotAPseudonym":](/1941318#comment_7828158
)
If an object can avoid being default constructed it should be. Very few objects I make ever have default constructors for this reason (it's not needed since again it adds overhead to put it in a non-invalid default state to be "safe"). Also your example is still less than ideal imo for various reasons. Firstly,@`a@` and @`b@` can clearly be @`const@` but they miss out on that because they're not being initialized with the data you're setting them to directly (@`a@` is being modified but that should be a for loop anyways to avoid bug prone logic with something as simple as trying to loop for a number of iterations, but really that is more opinion based since a while loop might be your own preference). Additionally, @`d@` can and should be @`const@` and be located in the inner scope for reasons previously mentioned. Const correctness is there to help the program be safer, right now one could accidentally write to any of those variables where in the original intent they were assumed to be constant throughout (after all, these are inputs, they don't appear to need to change at any point), and discontinuities between the programmer's mind and reality are what cause bugs.
Personally I'd write it like:
unsigned const a{ input\("a"\) };
unsigned const b{ input\("b"\) };
unsigned c{ 1 };
for \(unsigned i{ a }; i != 0; --i\) {
unsigned const d{ i \* b };
output\(d\);
c += d;
}
output\(c\);
Your point about temporary objects is valid, constructing expensive objects inside of loops usually isn't a good idea, but neither is assigning them. Remember, copy and move assignment both call a destructor of the old value just the same as it going out of scope or to the next loop iteration, and a constructor will still need to be invoked in the loop body somewhere each iteration since you aren't just whipping up classes out of thin air so it's really no different than if it was initialized as a local instance within the loop scope. In cases like that you may want to redesign your code so that it does not happen, but for integers or other primitive types you won't have issues since they'll be in registers and heavily optimized anyways, the location in scopes and const-ness of them is really just benefiting you for the most part at that point (and perhaps helping the compiler optimize a little better).
C++ Crazed
If an object can avoid being default constructed it should be. Very few objects I make ever have default constructors for this reason (it's not needed since again it adds overhead to put it in a non-invalid default state to be "safe"). Also your example is still less than ideal imo for various reasons. Firstly,
Personally I'd write it like:
unsigned const a{ input\("a"\) };
unsigned const b{ input\("b"\) };
unsigned c{ 1 };
for \(unsigned i{ a }; i != 0; --i\) {
unsigned const d{ i \* b };
output\(d\);
c += d;
}
output\(c\);
Your point about temporary objects is valid, constructing expensive objects inside of loops usually isn't a good idea, but neither is assigning them. Remember, copy and move assignment both call a destructor of the old value just the same as it going out of scope or to the next loop iteration, and a constructor will still need to be invoked in the loop body somewhere each iteration since you aren't just whipping up classes out of thin air so it's really no different than if it was initialized as a local instance within the loop scope. In cases like that you may want to redesign your code so that it does not happen, but for integers or other primitive types you won't have issues since they'll be in registers and heavily optimized anyways, the location in scopes and const-ness of them is really just benefiting you for the most part at that point (and perhaps helping the compiler optimize a little better).