All the other answers defend your lecturer’s rule 3.
Let me say that I agree with you: the rule is redundant and I wouldn’t advise it. It’s true that it theoretically prevents errors if you always add curly brackets. On the other hand, I’ve never encountered this problem in real life: contrary to what other answers imply, I’ve not once forgotten to add the curly brackets once they became necessary. If you use proper indentation, it becomes immediately obvious that you need to add curly brackets once more than one statement is indented.
The answer by Component 10 actually highlights the only conceivable case where this could really lead to an error. But on the other hand, replacing code via regular expression always warrants enormous care anyway.
Now let’s look at the other side of the medal: is there a disadvantage to always using curly brackets? The other answers simply ignore this point. But there is a disadvantage: it takes up a lot of vertical screen space, and this in turn can make your code unreadable because it means you have to scroll more than necessary.
Consider a function with a lot of guard clauses at the beginning (and yes, the following is bad C++ code but in other languages this would be quite a common situation):
void some_method(obj* a, obj* b)
{
if (a == nullptr)
{
throw null_ptr_error("a");
}
if (b == nullptr)
{
throw null_ptr_error("b");
}
if (a == b)
{
throw logic_error("Cannot do method on identical objects");
}
if (not a->precondition_met())
{
throw logic_error("Precondition for a not met");
}
a->do_something_with(b);
}
This is horrible code, and I argue strongly that the following is vastly more readable:
void some_method(obj* a, obj* b)
{
if (a == nullptr)
throw null_ptr_error("a");
if (b == nullptr)
throw null_ptr_error("b");
if (a == b)
throw logic_error("Cannot do method on identical objects");
if (not a->precondition_met())
throw logic_error("Precondition for a not met");
a->do_something_with(b);
}
Similarly, short nested loops benefit from omitting the curly brackets:
matrix operator +(matrix const& a, matrix const& b) {
matrix c(a.w(), a.h());
for (auto i = 0; i < a.w(); ++i)
for (auto j = 0; j < a.h(); ++j)
c(i, j) = a(i, j) + b(i, j);
return c;
}
Compare with:
matrix operator +(matrix const& a, matrix const& b) {
matrix c(a.w(), a.h());
for (auto i = 0; i < a.w(); ++i)
{
for (auto j = 0; j < a.h(); ++j)
{
c(i, j) = a(i, j) + b(i, j);
}
}
return c;
}
The first code is concise; the second code is bloated.
And yes, this can be mitigated to some extent by putting the opening brace on the previous line. So: if you insist on curly braces, at least put the opening brace on the previous line.
In short: don’t write unnecessary code which takes up screen space.
In the time since originally writing the answer I’ve mostly accepted the prevailing code style and use braces unless I can put the entire single statement on the previous line. I still maintain that not using redundant braces is usually more readable, and I have still never encountered a bug caused by this.
5. Use unsigned for variables that are >= 0
is a nice trick. If you're decrementing an unsigned int == 0, you'll get an underflow. Which can easily occur. – Ironbarkfor (unsigned i = 100; i >= 0; --i)
. – Assistant(i % 2 == 0)
contradicts (2). You are relying on operator precedence, and the meaning is of course((i % 2) == 0)
rather than(i % (2 == 0))
. I would classify rule 2 as "a valid sentiment but 'always' is wrong". – Eatmoni
is not "a variable that is >= 0`. It's >=0 except when it's expected to go negative to terminate the loop. So it should not be unsigned, and rule 5 does not say that it should be unsigned :-) – Eatmoni % 2 == 0
needs parentheses:(i % 2) == 0
. And, of course, if you do something likei = 2 * j + 1;
you need multiple parentheses:i = ((2 * j) + 1);
. Your code would end up looking like LISP (Lots of Infernal Stupid Parentheses. Not that that's what you asked about, but stupid rules lead to stupid code. Some of these guidelines are coding solutions for beginners errors. Most programmers don't stay beginners for long, and following beginners' rules is not a good idea. Learn to write correct code. – Conklinnull_ptr
– Stoicdelete
in modern C++. Always use smart pointers instead. – Epicarpstd::can<Worms>.open()
:) – Dyakif (condition) statement;
on a single line, which is rare. So I should be mostly safe from your kind of psychotic, but not entirely. Unfortunately I put the opening brace on the same line, so RMS will get me anyway. – Eatmonfor (int i = 0 ; 100 > i ; ++i)
(per Rule 4)... – Canzonex + 5 * y == z
groups, maybe you should take a course in algebra before doing any programming. – Barboza((x + 5) * y) == z
– Chromaticityif (5 == myVar)
. I like Yoda, but not that much. – Marlitemacro
... Hum ! – Garrity=
vs==
- but not bad enough to justify this. – Keare