The order of operations for arithmetic operators is something you were probably already familiar with from math class. But C++ has many more operators than that. To understand how the compiler will read an expression, we need to know the precedence (order) of them all. You can look up the full list in C++ references, but here is a simplified version:
With this in hand, we can see how something like bool beforeChristmas = month < 12 || (month == 12 && day < 25); is evaluated. Assume month = 12 and day=26:
This also explains why trying to write !x == 10 does not calculate “x does not equal 10”. The ! is evaluated first and only is applied to x. So we get !x. If x is a number, this just turns any value but 0 to 0 and turns 0 to 1. Then we compare that value to 10! To write that correctly we need to write !(x == 10) or x != 10.
Within each category of operator, there may be a sub-hierarchy with its own order. We know that * comes before +. But it is also true that && always comes before ||. That means that we could write the expression above as month < 12 || month == 12 && day < 25. The comparisons would happen first, then the &&, then the ||. But the expression is much easier to read when the parentheses are there.
When in doubt, use parentheses. They make your code easier to read and understand. Code that depends on every programmer correctly remembering each detail of the order of operations can easily result in bugs and make those bugs harder to spot.