Skip to content

Lab 3 Assignment

CT 301: C++ Fundamentals · Summer 2026
Lab 3: Arrays, Memory, and the Free Store
Source: learncpp.com · Instructor: Dr. Francisco R. Ortega

Overview

This is an explore-and-reflect lab. The goal is to learn by trying things, not to finish a polished homework. You will read a few short lessons, then play with three pieces that sit underneath Homework 2: how an array is just contiguous memory you walk with a pointer, and the two ways C++ manages memory on the free store. When you are done, you record a short video where you show what you tried and explain what you learned. There is no written report.

A note on style: the lecture slides use import std;. In this class, and in these labs, we will use #include (for example, #include <iostream>). Both are valid modern C++.
Why this matters for Homework 2. Your vector is an array in a buffer it owns, and its iterators are just pointers walking that array, so v[i] is pointer math. The buffer also keeps more room than it is using (a capacity larger than the size), which ordinary new[] cannot do but raw allocation plus placement new can. This lab is where you see all three for yourself.

Reading

Read these lessons on learncpp.com (each opens in a new tab). If a lesson ends with a Quiz time, do it and check the provided solution.

Lesson 12.7: Introduction to pointers
What a pointer is and how it refers to a location in memory.
Lesson 17.9: Pointer arithmetic and subscripting
How an array is contiguous memory, how p[i] equals *(p + i), and how a begin/end pointer pair walks it. Has a short Quiz time.
Lesson 19.1: Dynamic memory allocation with new and delete
Asking the free store for memory and giving it back, and what leaks and dangling pointers are.
Lesson 15.4: Introduction to destructors
How a destructor runs cleanup automatically when an object goes away.

Explore 1: an array is contiguous memory you walk with a pointer

An array's elements sit next to each other in memory, so a pointer can step through them. The begin / end / ++p loop below is exactly how a vector's iterators work. Run it.

#include <iostream>
int main() {
    int data[5] = {2, 4, 6, 8, 10};
    int* begin = data;           // points at the first element
    int* end   = data + 5;       // points one past the last
    for (int* p = begin; p != end; ++p)
        std::cout << *p << " ";
    std::cout << "\n";
    // p[i] and *(p + i) are the same thing:
    std::cout << begin[2] << " == " << *(begin + 2) << "\n";
    return 0;
}
Try. It prints 2 4 6 8 10 and then 6 == 6. Now change the loop to print the elements in reverse, from end - 1 down to begin. Why is end one past the last element instead of at it?

Explore 2: new[] and delete[] (allocate and construct together)

The everyday form. new[] allocates memory and constructs every element at once; delete[] destroys them all and frees the memory. Complete this little class, which owns a buffer this way, and run it (it should print 0 1 4 9).

#include <iostream>

class IntBuffer {
public:
    IntBuffer(int n) {
        // TODO: allocate an array of n ints with new[], and remember n
    }
    ~IntBuffer() {
        // TODO: free the array with delete[]
    }
    void set(int i, int value) { /* TODO: store value at index i */ }
    int  get(int i) const { /* TODO: return the value at index i */ }
    int  size() const { /* TODO: return how many ints this holds */ }
private:
    // TODO: a pointer to the array, and an int for the size
};

int main() {
    IntBuffer b(4);
    for (int i = 0; i < b.size(); ++i) b.set(i, i * i);
    for (int i = 0; i < b.size(); ++i) std::cout << b.get(i) << " ";
    std::cout << "\n";          // expect: 0 1 4 9
    return 0;                   // b's destructor frees the memory here
}
Try. On Compiler Explorer, add -fsanitize=address and run again. Then remove the delete[] from your destructor and watch the sanitizer report a leak. Put it back.

Explore 3: raw allocation and placement new (allocate and construct separately)

The form your vector uses. ::operator new grabs raw bytes with no constructors run; placement new constructs one object in that memory; an explicit destructor call destroys one; and ::operator delete frees the bytes. Run this as is, then change it as the prompts ask.

#include <iostream>
#include <new>     // placement new

struct Noisy {
    int id;
    Noisy(int i) : id(i) { std::cout << "construct " << id << "\n"; }
    ~Noisy()             { std::cout << "destroy "   << id << "\n"; }
};

int main() {
    // 1. Allocate RAW memory for 4 Noisy objects. NONE are constructed yet.
    void* raw = ::operator new(4 * sizeof(Noisy));
    Noisy* buf = static_cast<Noisy*>(raw);
    std::cout << "room for 4, constructed 0 so far\n";

    // 2. Construct only TWO, in place, with placement new.
    new (buf + 0) Noisy(1);
    new (buf + 1) Noisy(2);
    // buf[2] and buf[3] are allocated but NOT constructed. Leave them alone.

    // 3. Destroy the two we built by calling the destructor explicitly. No delete.
    (buf + 0)->~Noisy();
    (buf + 1)->~Noisy();

    // 4. Free the raw bytes (this calls no destructor).
    ::operator delete(raw);
    return 0;
}
Try. Run it and read the output. You made room for four but constructed only two: capacity four, size two. Now construct a third object in buf + 2, print its id, and destroy it before you free.
Compare. Why can Explore 2 never leave a slot allocated but not constructed, while Explore 3 can? That difference is the reason a vector uses this second form.

Reflect and Record

Record a short video (about 3 to 5 minutes) and upload it to YouTube as Unlisted. In it:

This is a reflection, not a presentation. Rough is fine. There is no need to use AI, as you are graded on effort and on showing your own exploration. If you get stuck, you can say so in the video and still get the grade.

Grading

Labs are graded as complete or incomplete.

Full credit
You explored the three programs in a compiler and recorded a short video that shows your work and explains the ideas in your own words.
Zero
No submission, or no real try.

The labs together are worth 5 percent of your course grade.

How to Submit

Upload your video to YouTube as Unlisted, and submit the link (paste it into the Canvas assignment). Make sure the link is Unlisted, not Private, or we cannot view it. Make sure you do not use your phone. Produce a video with your face and the screen showing what you learned. 5 minutes is more than enough. 

Appendix: Online C++ Compilers

Any of the tools below will run the reading examples in your browser, with no local setup. Remember to use #include online, not import std;.

Our course toolchain is GCC 15.2 with -std=c++26. Only Compiler Explorer lets you set that exact combination. The other tools run an older fixed compiler, which is fine for these basic examples.

Compiler Explorer (godbolt.org) RECOMMENDED
The best match for our course. Lets you pick the exact compiler and see results and assembly.
How to use:
  1. In the compiler dropdown, choose x86-64 gcc 15.2.
  2. In the Compiler options box, type -std=c++26.
  3. To run the program (not just compile it), open the Execution or Add tool > Executor pane.
  4. Use the Share button to get a link to your code.
Python Tutor (pythontutor.com)
Best for seeing what your code does. It steps through line by line and shows variables and memory. Very useful in later labs on pointers.
How to use:
  1. Select C++ from the language menu.
  2. Type your code and press Visualize Execution.
  3. Step forward and back to watch values change.
Note: it runs an older fixed compiler, so you cannot set GCC 15.2 or -std=c++26 here. That is fine for the basic examples.
OnlineGDB (onlinegdb.com)
A simple editor with a real step-through debugger, good for watching a program run one line at a time.
How to use:
  1. Set the language (top right) to C++.
  2. Use the settings gear to pick the C++ standard.
  3. Press Run, or Debug to step through the code.
Note: older fixed GCC, may not offer c++26. Fine for the basic examples.
Wandbox (wandbox.org)
The quickest paste and run, with a shareable link.
How to use:
  1. Pick the newest GCC from the compiler list.
  2. Choose C++26 from the standard menu, or add -std=c++26 to the options.
  3. Press Run, then Share for a link.