1 of 48

C++ For Interviews

Michael Sukkarieh

2 of 48

Introduction

  • Michael Sukkarieh
  • Currently SWE @ Google, Stadia Games & Entertainment team
  • Previously McGill SE, part of GameDev McGill
  • During degree have done tech interviews at:
    • Ubisoft, EA, Activision, Riot Games, Autodesk, Microsoft, Google, Apple, NVIDIA,
    • Bold == full time interview

3 of 48

Disclaimer

  • Everything in this talk is from personal experience and is not affiliated/referring to how interviewing at Google works!
    • I have never given an interview at Google, and am not interview trained (as of this talk)
  • I will only be talking about C++ and C++ questions, you will also want to prepare for general algorithm type questions (esp for large companies)
    • C++ questions like this are commonly only asked if the job will guaranteed to use C++ (ex. game dev)

4 of 48

Goals of the talk

  • Explain the major differences between C++ and C/Java
  • Discuss aspects of C++ that are commonly asked during technical interviews
    • Const correctness?
    • Memory allocation (stack and heap)
    • Bit twiddling
    • Dynamic dispatching (i.e. virtual functions)
  • Hopefully make C++ less intimidating and more interesting

5 of 48

History

  • First introduced in 1985, developed by Danish computer scientist Bjarne Stroustrup
  • Developed to combine OO with the speed and power of C
    • Was first called “C with classes”, but was later renamed to C++ as a play on words of the ++ increment operator in C
  • Further updates to the language have been made in 2011 (C++11), 2014 (C++14), and 2017 (C++17), and now 2020 (C++20???)

6 of 48

Industries using C++

  • Any industry requiring high performance, efficient code:
    • Video games (Ubisoft, EA, Bethesda, Rockstar, etc)
    • Backend Infrastructure (Google, Microsoft, Amazon, etc)
    • Financial Applications (Bloomberg, etc)
    • Embedded Systems
    • and much more

7 of 48

Hello World

1 - #include preprocessor command (similar to C)

3 - using namespace declaration (discussed later)

5 - main method entry point (similar to C)

6 - cout is a stream which outputs to stdout (similar to C or printf). Can also just use printf

8 of 48

Basic Similarities (C like)

  • Core programming tools (if, while loop, for loop, variable declaration) are the similar to C/Java (C++ is strongly typed, unlike languages like python or js)

9 of 48

C++ vs C

10 of 48

C++ is Object Oriented

  • Unlike C, C++ allows for object-oriented programming techniques
    • Classes, inheritance, polymorphism, etc
  • Classes have constructors (called during creation, like Java) and destructors (called during deletion)
  • Class methods/variables have accessibility restrictions (similar to Java)

11 of 48

new/delete instead of malloc/free

  • C++ introduces two new keywords for dynamic memory allocation: new and delete
  • Instead of using malloc to allocate memory on the heap, you can simply call new to do it (similar to Java)
  • However, malloc can still be used and is more powerful than new and may be needed in some cases (ex. custom memory manager)

12 of 48

Generic Programming with Templates

  • Similarly to Java, C++ allows for generic programming using templates
    • Generic programming allows a developer to generalize a class definition to work with different data types (which is specified during instance creation)

13 of 48

Namespaces

  • Namespaces allow you to create a new scope which identifiers can be defined in
  • This allows you to have multiple different classes/methods be named the same, as long as they are defined in different namespaces, there are no conflicts
  • Example: the C++ standard library is defined under the std namespace, and this library uses very common identifiers(

14 of 48

C++ standard library

  • One of the main things that make using C annoying is that lack of standard library, but this is (mostly) not the case in C++
  • The C++ standard library provides common data structures and algorithms
    • strings (no need to always use char* !), vectors, queue, etc
    • sorting, binary search, etc

15 of 48

C++ vs Java

16 of 48

Manual Memory Management

  • C++ does not have a garbage collector, and therefore the developer is required to deallocate all memory they are using throughout the execution of the program
  • If the developer fails to do this, a memory leak will occur: memory which is allocated on the heap but the developer has lost a reference to it!

17 of 48

Instance Allocation on the Stack

  • In Java, every instance is required to be initialized (using new) before being used
  • In C++, you are able to have a instance be allocated on the heap (using a pointer and new), or have the instance be allocated on the stack

18 of 48

Smart Pointers Prereq: RAII

  • Resource Acquisition Is Initialization (RAII) is a programming idiom commonly related to objects which have a primary purpose of holding a resource (ex. a container class) and was first introduced in C++ by Stroustrup
  • For a class that follows RAII, acquiring the resource (Resource Acquisition) is required to initialize the object (Is Initialization)

19 of 48

Smart Pointers

  • Smart pointers simulate a normal pointer (now called raw pointer), but also provide for automatic memory management using the RAII idiom
  • Two main smart pointers used in C++: unique_ptr and shared_ptr
    • unique_ptr is the only owner of the pointer (this is enforced using some concepts covered later). In other words, a unique_ptr object cannot be copied
    • shared_ptr may be one of many owners of the pointer (i.e. copying a shared_ptr is allowed)
  • Smart pointers allow the developer to clearly indicate ownership of a resource and transfer of ownership

20 of 48

Smart Pointer Example

21 of 48

Operator Overloading

  • C++ allows you to redefine (“overload”) what the common operators (+, =, etc) do when used with your user defined data type (class)
  • Extremely useful, especially once we get into more memory management techniques!

22 of 48

C++ Interview Topics

23 of 48

Main Topics

  • Memory allocation and management
  • Working with bits (bit twiddling)
  • Dynamic Dispatching

24 of 48

Memory Allocation and Management

  • Understanding how memory allocation and proper management works is important, and is a common topic for interviews
  • Things like:
    • Stack vs Heap (including pointers)
    • Working with bytes
    • Virtual memory potentially

25 of 48

Program Memory Layout

  • Basic program memory layout (non-virtual configuration)
  • Stack is usually allocated all at once for a function call, since we know the variables that will be allocated
  • Heap is free memory which we can request memory from the OS

26 of 48

Program Memory Layout

  • Example question: What is faster, allocating on the stack or on the heap?

27 of 48

Program Memory Layout

  • Example question: What is faster, allocating on the stack or on the heap?
  • Answer: STACK. Allocation on the heap requires the OS to find a page (memory block), while allocation on the stack is well defined when entering a new call stack

28 of 48

Program Memory Layout

  • Example question: What is faster, allocating on the stack or on the heap?
  • Answer: STACK. Allocation on the heap requires the OS to find a page (memory block), while allocation on the stack is well defined when entering a new call stack

29 of 48

Working on the bit level

  • Advanced techniques may require you to work with memory on a bit level (ex. masks, serialization, etc)
  • Example: If you’re given a list of unsinged int’s (16 bits) but you want a list of unsigned char’s (8 bits), how would you do it?

30 of 48

Working on the bit level

  • Advanced techniques may require you to work with memory on a bit level (ex. masks, serialization, etc)
  • Example: If you’re given a list of unsigned int’s (16 bits) but you want a list of unsigned char’s (8 bits), how would you do it?
    • Answer: Use a mask to extract info from the long int’s:

31 of 48

Working on the bit level

  • Advanced techniques may require you to work with memory on a bit level (ex. masks, serialization, etc)
  • Example: If you’re given a list of unsigned int’s (16 bits) but you want a list of unsigned char’s (8 bits), how would you do it?
    • Answer: Use a mask to extract info from the long int’s:

32 of 48

Virtual Methods and Dynamic Dispatch in C++

  • In Java, we can override superclass methods in the subclass and they will always be called if we have a instance of the subclass (even if it contained within a superclass reference!). In other words, java always adopts dynamic dispatching
  • This is not the case with C++, by default static dispatching is used but we can force dynamic dispatching using the virtual keyword

33 of 48

Example

34 of 48

Virtual Method Example and Explanation

source: https://www.learncpp.com/cpp-tutorial/125-the-virtual-table/

  • To implement dynamic dispatching, most C++ compilers will use a virtual table (vtable)
  • Each class which has a virtual method, or is derived from a class that does, has a vtable and each instance of that class has a pointer to its vtable
  • Therefore, whenever a virtual function is called we are able to index the vtable to find the proper method to call

35 of 48

Possible Questions

  • Why would we want to set a destructor to be virtual?

36 of 48

Possible Questions

  • Why would we want to set a destructor to be virtual?
    • Answer: If we have a deriving class which allocates it’s own memory that is freed in the destructor, the destructor of the parent must be virtual to ensure the proper memory is freed

37 of 48

Possible Questions

  • Why would we want to set a destructor to be virtual?
    • Answer: If we have a deriving class which allocates its own memory that is freed in the destructor, the destructor of the parent must be virtual to ensure the proper memory is freed
  • What is the overhead/cost of calling a virtual function?

38 of 48

Possible Questions

  • Why would we want to set a destructor to be virtual?
    • Answer: If we have a deriving class which allocates its own memory that is freed in the destructor, the destructor of the parent must be virtual to ensure the proper memory is freed
  • What is the overhead/cost of calling a virtual function?
    • Answer: we incur an extra pointer dereference, because we need to lookup the function pointer in the vtable

39 of 48

Misc C++ Concepts

40 of 48

References

  • References can be used to create an alias for a variable (declared using the & symbol, similar to how pointers are declared using *)
  • They are very powerful because they allow us to pass values by reference into functions, as well as prevent unnecessary copies of data

41 of 48

Passing by reference

42 of 48

Reference vs Pointer

  • References and pointers both allow us to pass objects in as reference and prevent unnecessary copies
  • However, the main benefit of references is that they cannot be NULL (we don’t need to worry about dereferences a null pointer)
    • The variable they are referring to also cannot be changed (unlike regular pointers)
  • Usually, pointer parameters are used to indicate that the object passed in will be changed by the function, while const references are used simply for efficiency reasons

43 of 48

Const and Const Correctness

  • const is a sometimes confusing, but very powerful and commonly used keyword in C++
  • Anything declared as const is unchangeable (i.e. is constant)
  • However, class methods can also be declared const, which “enforces” that the method does not change the internal state of the instance
    • A class method must be declared const in order to be called by a const instance

44 of 48

Const Class Methods Example

45 of 48

Extra topics that I wish I could cover

  • Moving vs Copying (move semantics, rvalue references)
    • Move/Copy constructors
    • default/delete
  • Macros
  • Smart pointers

46 of 48

Resources

47 of 48

Questions?

48 of 48

Thank you!