Unless you ditch optimizations completely, it is hard to know without looking at the generated asm. Of course you can make educated guesses.
struct S {
int m_field;
int field() { return m_field; }
void field(int c) { m_field = x; }
}
just to future proof the field access. Don't bother with the access functions until they are actually needed.underneath there is literally assembly to take current state, push it to the stack, then jump into another location in memory and start executing.
And then when done, do the reverse. jump back to another memory location and pop everything back off the aforementioned stack and into registers.
interrupts are also control flow but, again, there are no conditionals there.
control flow is about the order of execution, one common way to get there is using conditionals, but it's not the only way.
Having said that, even if you disagree with Andrew's wording, the overarching idea remains. You always know explicitly if the flow changes.
However I think the notion that “flow control” has to do only with conditionals is not a common one. FWIW the definition on Wikipedia, which aligns with my experience is not this restrictive… the lowly goto is flow control. Basically anything that controls the program location is flow control.
Yeah, flow control isn't just conditional jumps. You can kinda treat branchless code as a form of flow control as well.
That's the common understanding of flow control, the other poster is right in that it's not typically just conditionals. There are a few posters who were under that misapprehension, but that's never been the common understanding of it, it's just that conditionals are typically where people worry over flow control because otherwise it's linear.
And flow control and indirection are not two concepts I’ve ever grouped together as complementary either. A function call is not something I’ve ever heard as “indirection”.
If anything, I would argue that explicit accessors make it clearer because in e.g. C# you can't write a method that looks like a getter (but mutates state) by accidentally naming it as such. If someone made something a property, that's because they thought its semantics are property-like, which includes not mutating global state. Sure, people will still get that wrong occasionally, just as they run mutating "get" methods, but it is surprisingly rare.
Suppose you include a logging statement in your accessor, which hides a race condition. You're gonna tear your hair out.
When I was new to their corresponding GUI frameworks, the dot + property notation was appealing because it looked clean. However, as I got more experienced I'm no longer seeing the advantage of saving two parentheses characters at the expense of potentially hiding function calls where anything can happen.
I'm not sure why D joined the club given it doesn't have a corresponding de facto GUI framework, and its users even discourage it.
So I overrode the field access that operated directly on the byte array.
PS: It was in Kotlin, using @get/@set, but it doesn't matter for the philosophy.
Attribute access is reading a value, invoking a function is different (as mentioned, using a stack, etc.), although it is certainly possible a function only reads and returns a value.
All that to say my answer is yes, providing flow control mechanisms makes it flow control... and falling trees make a sound!