1. call by [?]
struct Tick { int px; int qty; };
void upd1(Tick& t) {
/* blank 1 */
}
void upd2(Tick* t) {
/* blank 2 */
}
void upd3(Tick t) {
t.qty += 1;
}
int main() {
Tick a{100, 1};
upd1(/* blank 3 */); // a must be {100, 2} in here
upd2(/* blank 4 */); // a must be {100, 3} in here
}
Part 1.
You’re writing a nanosecond-critical feed handler. now implement upd1/2 ; need to proceed with increasing each object’s qty by 1.
Part 2.
(1) For a hot path called millions of times per second, pick which signature(s) you’d expose and why. Discuss performance, safety, and API clarity.
(2) How does passing by reference/pointer affect inlining?
(3) How does passing by reference/pointer affect aliasing assumptions?
(4) What actually gets copied in (upd3)? When could copy elision help or not help here?
(5) How does ABI pass small aggregates vs. large ones, and why might that impact latency?
(6) When would you prefer const Tick&? What about Tick&& ?
Answer
Answer (Part 1)
struct Tick { int px; int qty; };
void upd1(Tick& t) { t.qty += 1; }
void upd2(Tick* t) { if (t) t->qty += 1; }
Answer (Part 2)
(1) I'd expose upd1 (by reference). Performance: avoids copy overhead, direct memory access; hot path demands minimal latency. Safety: no null risk like pointer. API clarity: intent to modify is clear without deref syntax.
(2) References/pointers can hinder inlining if compiler can't prove no side effects or aliasing; value passing often inlines easier as locals are optimizable.
(3) References/pointers introduce potential aliasing; compiler assumes they might point to same memory, restricting optimizations like reordering. Use restrict or analysis to mitigate.
(4) Entire Tick copied on call; elision (RVO/NRVO) can help if return, but not here—function void, modification discarded. No elision for param copy.
(5) Small aggregates like Tick passed in registers (e.g., x86-64: up to 2 ints); large ones on stack, adding indirection/load latency. Impacts hot path by extra cycles for memory ops.
(6) const Tick&: for read-only access, prevents mutation, enables optimizations. Tick&&: for move semantics in overloads, like perfect forwarding or stealing resources efficiently.