← intercontinental exchange Interview Insights

intercontinental exchange·Software Engineer·Technical Phone Screen·Intermediate

Intermediate
Jul 2026

Summary

Technical phone screen for a Software Engineer role at Intercontinental Exchange. The questions were solidly C++ focused, which I half expected but still felt underprepared for on the polymorphism side.

Questions Asked (2)

Q1

What are the key differences between std::vector and std::list in C++, and when would you choose one over the other?

Technical Trade-offsAlgorithms & Data Structures
Author's notes

I knew the surface stuff: vector is contiguous memory, list is pointer-chained nodes.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by defining the core data structures: std::vector as a dynamic array with contiguous memory and std::list as a doubly-linked list with non-contiguous nodes. Then compare their performance characteristics (access, insertion, deletion, memory overhead) and discuss trade-offs in real-world scenarios, especially in low-latency systems like those at ICE. Conclude with guidance on when to choose each based on access patterns, frequency of insertions/deletions, and memory constraints.

Pro tip: Mention that in latency-sensitive trading systems, std::vector is often preferred due to cache locality and predictable performance, but std::list can be useful when stable references and frequent mid-sequence insertions/removals are needed. Also note that std::deque or intrusive lists are sometimes better alternatives, showing deeper knowledge.

1. Define the data structures

Briefly explain that std::vector is a dynamic array with contiguous memory, while std::list is a doubly-linked list with nodes scattered in memory.

2. Compare performance characteristics

Discuss time complexity for access (O(1) vs O(n)), insertion/deletion at ends and middle (amortized O(1) vs O(1) with iterator), and memory overhead (contiguous vs per-node overhead).

3. Highlight iterator and reference stability

Explain that std::list provides stable iterators and references except for erased elements, while std::vector may invalidate them on reallocation or insertion/deletion.

4. Discuss cache efficiency and real-world implications

Emphasize that std::vector's contiguous memory leads to better cache locality and performance in practice, especially for traversal, while std::list suffers from cache misses.

5. Provide selection criteria

Conclude with when to choose each: use std::vector for frequent random access, traversal, and when memory overhead matters; use std::list for frequent insertions/deletions in the middle and when iterator stability is required.

Key Points to Mention

  • Contiguous memory vs non-contiguous nodes
  • Time complexity: O(1) random access for vector vs O(n) for list; O(1) insertion/deletion at known position for list vs O(n) for vector (except at end)
  • Memory overhead: vector has minimal overhead but may over-allocate; list has per-node overhead (two pointers) and no over-allocation
  • Iterator invalidation: vector invalidates on reallocation and insertion/deletion (except at end); list only invalidates on erasure of the element
  • Cache locality and performance: vector generally faster due to prefetching and cache efficiency
  • Use cases: vector for frequent access, list for frequent mid-sequence modifications; consider std::deque or intrusive lists as alternatives

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q2

Can you explain what polymorphism means in C++, covering both compile-time and runtime forms?

Technical Trade-offsSystem Design
Author's notes

Went with templates and overloading for compile-time, virtual functions for runtime.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by defining polymorphism as the ability of objects of different types to respond to the same interface, then clearly distinguish compile-time (static) and runtime (dynamic) forms. For each form, explain the mechanism (e.g., function overloading/templates vs. virtual functions) and provide a simple code example. Finally, discuss trade-offs such as performance, flexibility, and design implications, tying back to real-world system design.

Pro tip: Mention that runtime polymorphism via virtual functions introduces a vtable lookup overhead, which can be mitigated by devirtualization or using CRTP for compile-time polymorphism. This shows awareness of performance-critical systems, which is highly relevant for trading platforms.

1. Define Polymorphism

Give a clear, concise definition: polymorphism allows different types to be treated through a common interface, enabling code reuse and flexibility.

2. Explain Compile-Time Polymorphism

Describe static polymorphism achieved via function overloading, operator overloading, and templates. Emphasize that resolution happens at compile time, leading to zero runtime overhead.

3. Explain Runtime Polymorphism

Describe dynamic polymorphism using inheritance and virtual functions. Explain how the vtable and vptr enable dynamic dispatch at runtime, allowing behavior to be determined by the actual object type.

4. Compare and Contrast

Highlight key differences: compile-time is faster and type-safe but less flexible; runtime is more flexible but incurs overhead and requires careful design (e.g., virtual destructors).

5. Relate to System Design

Discuss when to use each form in system design, considering performance, extensibility, and maintainability. For example, use templates for high-performance generic code and virtual functions for plugin architectures.

Key Points to Mention

  • Function overloading and operator overloading as compile-time polymorphism
  • Templates and generic programming for compile-time polymorphism
  • Virtual functions and inheritance for runtime polymorphism
  • Vtable and vptr mechanism for dynamic dispatch
  • Performance trade-offs: compile-time has no runtime overhead, runtime incurs vtable lookup
  • Use of virtual destructors to avoid undefined behavior
  • CRTP (Curiously Recurring Template Pattern) as a compile-time alternative to virtual functions

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.