Write a Usage Example for a Resource-Owning C++ Class and Explain Its Semantics

Quick Overview

A C++ internship screen exercise: read an unfamiliar class that owns a heap array and write an example program showing callers how to use it correctly. It tests code comprehension and C++ fundamentals such as RAII, deleted copy operations, move semantics, noexcept, explicit constructors and const-correctness.

Write a Usage Example for a Resource-Owning C++ Class and Explain Its Semantics

Company: Apple

Role: Software Engineer

Category: Software Engineering Fundamentals

Difficulty: easy

Interview Round: Technical Screen

In a technical screen for a software engineering internship, the coding portion is not an algorithm problem. The interviewer hands you a small C++ class you have never seen and asks you to write an example program that shows how the class is meant to be used. AI assistance is allowed while you write the code, and while you work the interviewer asks C++ fundamentals questions about what your example does and why it compiles. The exact class from the interview was not disclosed. To make this practice self-contained, use the following representative stand-in, a fixed-capacity buffer that owns a heap-allocated array: ```cpp #include <cstddef> #include <stdexcept> #include <utility> class IntBuffer { public: explicit IntBuffer(std::size_t capacity) : data_(new int[capacity]), capacity_(capacity), size_(0) {} ~IntBuffer() { delete[] data_; } IntBuffer(const IntBuffer&) = delete; IntBuffer& operator=(const IntBuffer&) = delete; IntBuffer(IntBuffer&& other) noexcept : data_(std::exchange(other.data_, nullptr)), capacity_(std::exchange(other.capacity_, 0)), size_(std::exchange(other.size_, 0)) {} IntBuffer& operator=(IntBuffer&& other) noexcept { if (this != &other) { delete[] data_; data_ = std::exchange(other.data_, nullptr); capacity_ = std::exchange(other.capacity_, 0); size_ = std::exchange(other.size_, 0); } return *this; } void push(int value) { if (size_ == capacity_) { throw std::length_error("IntBuffer is full"); } data_[size_++] = value; } int at(std::size_t index) const { if (index >= size_) { throw std::out_of_range("IntBuffer index out of range"); } return data_[index]; } std::size_t size() const { return size_; } std::size_t capacity() const { return capacity_; } private: int* data_; std::size_t capacity_; std::size_t size_; }; ``` ### Constraints and Clarifications - Treat the class as given: you may not edit it while writing the example (Part 2 asks what you would change). - The example must compile and run without undefined behavior. Lines that are meant to illustrate a compile error may appear only as comments. - Standard library headers such as `<iostream>` and `<vector>` are available. ### Clarifying Questions - Is the example meant to read as documentation for other developers, as a quick smoke test, or both? - Should error cases be demonstrated by catching the exceptions the class throws, or by checking `size()` and `capacity()` before calling? - Which C++ standard does the team build with? (`std::exchange` requires C++14 or later.) ### Part 1 — Write the usage example Write a short program (a `main()` plus any small helper functions) that shows a new user of `IntBuffer` how to use it correctly. The example should exercise every public member, show what happens on each failure path the class signals, and make clear which operations the class deliberately allows and which it forbids. ```hint Read the special members first Before writing any calls, look at which constructors and assignment operators are defined, deleted, or marked `explicit` or `noexcept`; together they tell you how the author intends objects of this type to be created, passed around and stored. ``` #### What This Part Should Cover - Coverage of construction, insertion, element access, size queries and both exception paths - Ownership handled the way the class intends: passing, returning and storing objects without attempting a copy - Correct behavior around moved-from objects, with no use of a moved-from buffer that assumes it still holds data - Readability as documentation: comments that explain why each usage is right or wrong ### Part 2 — Explain the C++ behind your example While reviewing your example, the interviewer asks C++ fundamentals questions about it. The exact questions from the interview were not reported; the ones below are the questions this class naturally raises: 1. Why are the copy constructor and copy assignment operator deleted? What would go wrong if the compiler-generated versions were used? 2. After `IntBuffer b = std::move(a);`, what state is `a` in, and what is it still safe to do with `a`? 3. Why are the move constructor and move assignment operator marked `noexcept`? What would change for a `std::vector` of `IntBuffer` objects if they were not? 4. What does `explicit` on the constructor prevent? Give a line that would compile without it and does not compile with it. 5. Why are `at`, `size` and `capacity` declared `const`, and what happens if a function that receives a `const IntBuffer&` calls `push`? 6. If you were allowed to change the class, how would you remove the hand-written destructor and move operations, and what new problem would you have to watch for? ```hint Follow the pointer For each question, trace what happens to `data_`, and to the `size_` and `capacity_` that describe it, when two objects could end up referring to the same array. ``` #### What This Part Should Cover - Ownership reasoning: shallow copies, double deletion and the rule of three/five - Move semantics and the documented moved-from state of this particular class - How `noexcept` interacts with standard containers and exception guarantees - `const`-correctness, implicit conversions, and the trade-offs of refactoring toward standard library members ### What a Strong Answer Covers - An example that compiles, runs cleanly and would genuinely help a new user of the class - Explanations tied to the specific members of `IntBuffer` rather than recited definitions - Precise language about undefined behavior versus a compile error versus a thrown exception - Awareness of exception safety in `push`, the constructor and the move operations - Clear reasoning about when hand-written special member functions are justified ### Follow-up Questions - The move assignment operator checks `this != &other`. Trace what would happen on a self-move without that check. - How would you turn `IntBuffer` into a class template over the element type, and what changes if the element type's move constructor can throw? - Write a test that would fail if someone accidentally re-enabled copying with a shallow copy. - Should `at` return `int`, `const int&`, or offer both `const` and non-`const` overloads? What does each choice allow callers to do?

Overview: A C++ internship screen exercise: read an unfamiliar class that owns a heap array and write an example program showing callers how to use it correctly. It tests code comprehension and C++ fundamentals such as RAII, deleted copy operations, move semantics, noexcept, explicit constructors and const-correctness.

|Home/Software Engineering Fundamentals/Apple
Apple logo
Apple
Sep 23, 2026
easySoftware EngineerTechnical ScreenSoftware Engineering Fundamentals
0
0

In a technical screen for a software engineering internship, the coding portion is not an algorithm problem. The interviewer hands you a small C++ class you have never seen and asks you to write an example program that shows how the class is meant to be used. AI assistance is allowed while you write the code, and while you work the interviewer asks C++ fundamentals questions about what your example does and why it compiles.

The exact class from the interview was not disclosed. To make this practice self-contained, use the following representative stand-in, a fixed-capacity buffer that owns a heap-allocated array:

#include <cstddef>
#include <stdexcept>
#include <utility>

class IntBuffer {
public:
    explicit IntBuffer(std::size_t capacity)
        : data_(new int[capacity]), capacity_(capacity), size_(0) {}

    ~IntBuffer() { delete[] data_; }

    IntBuffer(const IntBuffer&) = delete;
    IntBuffer& operator=(const IntBuffer&) = delete;

    IntBuffer(IntBuffer&& other) noexcept
        : data_(std::exchange(other.data_, nullptr)),
          capacity_(std::exchange(other.capacity_, 0)),
          size_(std::exchange(other.size_, 0)) {}

    IntBuffer& operator=(IntBuffer&& other) noexcept {
        if (this != &other) {
            delete[] data_;
            data_ = std::exchange(other.data_, nullptr);
            capacity_ = std::exchange(other.capacity_, 0);
            size_ = std::exchange(other.size_, 0);
        }
        return *this;
    }

    void push(int value) {
        if (size_ == capacity_) {
            throw std::length_error("IntBuffer is full");
        }
        data_[size_++] = value;
    }

    int at(std::size_t index) const {
        if (index >= size_) {
            throw std::out_of_range("IntBuffer index out of range");
        }
        return data_[index];
    }

    std::size_t size() const { return size_; }
    std::size_t capacity() const { return capacity_; }

private:
    int* data_;
    std::size_t capacity_;
    std::size_t size_;
};

Constraints and Clarifications

  • Treat the class as given: you may not edit it while writing the example (Part 2 asks what you would change).
  • The example must compile and run without undefined behavior. Lines that are meant to illustrate a compile error may appear only as comments.
  • Standard library headers such as <iostream> and <vector> are available.

Clarifying Questions Guidance

  • Is the example meant to read as documentation for other developers, as a quick smoke test, or both?
  • Should error cases be demonstrated by catching the exceptions the class throws, or by checking size() and capacity() before calling?
  • Which C++ standard does the team build with? ( std::exchange requires C++14 or later.)

Part 1 — Write the usage example

Write a short program (a main() plus any small helper functions) that shows a new user of IntBuffer how to use it correctly. The example should exercise every public member, show what happens on each failure path the class signals, and make clear which operations the class deliberately allows and which it forbids.

What This Part Should Cover Guidance

  • Coverage of construction, insertion, element access, size queries and both exception paths
  • Ownership handled the way the class intends: passing, returning and storing objects without attempting a copy
  • Correct behavior around moved-from objects, with no use of a moved-from buffer that assumes it still holds data
  • Readability as documentation: comments that explain why each usage is right or wrong

Part 2 — Explain the C++ behind your example

While reviewing your example, the interviewer asks C++ fundamentals questions about it. The exact questions from the interview were not reported; the ones below are the questions this class naturally raises:

  1. Why are the copy constructor and copy assignment operator deleted? What would go wrong if the compiler-generated versions were used?
  2. After IntBuffer b = std::move(a); , what state is a in, and what is it still safe to do with a ?
  3. Why are the move constructor and move assignment operator marked noexcept ? What would change for a std::vector of IntBuffer objects if they were not?
  4. What does explicit on the constructor prevent? Give a line that would compile without it and does not compile with it.
  5. Why are at , size and capacity declared const , and what happens if a function that receives a const IntBuffer& calls push ?
  6. If you were allowed to change the class, how would you remove the hand-written destructor and move operations, and what new problem would you have to watch for?

What This Part Should Cover Guidance

  • Ownership reasoning: shallow copies, double deletion and the rule of three/five
  • Move semantics and the documented moved-from state of this particular class
  • How noexcept interacts with standard containers and exception guarantees
  • const -correctness, implicit conversions, and the trade-offs of refactoring toward standard library members

What a Strong Answer Covers Guidance

  • An example that compiles, runs cleanly and would genuinely help a new user of the class
  • Explanations tied to the specific members of IntBuffer rather than recited definitions
  • Precise language about undefined behavior versus a compile error versus a thrown exception
  • Awareness of exception safety in push , the constructor and the move operations
  • Clear reasoning about when hand-written special member functions are justified

Follow-up Questions Guidance

  • The move assignment operator checks this != &other . Trace what would happen on a self-move without that check.
  • How would you turn IntBuffer into a class template over the element type, and what changes if the element type's move constructor can throw?
  • Write a test that would fail if someone accidentally re-enabled copying with a shallow copy.
  • Should at return int , const int& , or offer both const and non- const overloads? What does each choice allow callers to do?
Loading comments...