Skip to content

Quiz 11 — RAII and Smart Pointers

Ten questions on tying a resource's lifetime to an object's lifetime, and on choosing between unique_ptr, shared_ptr and weak_ptr.

Attempt all of them closed-book, then mark yourself against the answers.

Concepts: RAII · scope-based cleanup · unique_ptr · shared_ptr · weak_ptr · ownership cycles · custom deleters.


Q1. (MCQ) RAII means:

  • A. Resource Acquisition Is Initialisation — acquire in a constructor, release in a destructor
  • B. Run After Initialisation — start work once a flag is set
  • C. Reference And Interface — an interface for references
  • D. a way to avoid destructors

Q2. (true/false) std::unique_ptr can be copied with =.

Q3. (multiple-select) For which jobs is std::unique_ptr the right choice? Select all that apply.

  • A. A library that owns its items
  • B. A logger shared by several components that closes when the last is gone
  • C. A factory's returned shape, owned by the caller
  • D. An observer that must not keep the subject alive

Q4. (predict) Write the single output line.

#include <iostream>
#include <memory>

struct Res {
    const char* name;
    explicit Res(const char* n) : name(n) { std::cout << '+' << name << ' '; }
    ~Res() { std::cout << '-' << name << ' '; }
};

int main() {
    std::cout << "a ";
    {
        auto p = std::make_unique<Res>("x");
        std::cout << "b ";
    }
    std::cout << "c\n";
}

Q5. (predict) Write the output.

#include <iostream>
#include <memory>

int main() {
    auto sp = std::make_shared<int>(42);
    std::weak_ptr<int> wp = sp;
    std::cout << "count " << sp.use_count() << '\n';
    sp.reset();
    if (auto locked = wp.lock()) {
        std::cout << "alive\n";
    } else {
        std::cout << "gone\n";
    }
}

Q6. (debug) Two nodes point at each other and neither is ever destroyed. Explain the cycle and fix it by changing one member.

#include <memory>

struct Node {
    std::shared_ptr<Node> neighbour;
};

Q7. (predict) Write the output.

#include <iostream>
#include <memory>

struct Device {
    int id;
    explicit Device(int i) : id(i) { std::cout << "on " << id << ' '; }
    ~Device() { std::cout << "off " << id << ' '; }
};

int main() {
    std::vector<std::unique_ptr<Device>> shelf;
    shelf.push_back(std::make_unique<Device>(1));
    shelf.push_back(std::make_unique<Device>(2));
    std::cout << "| ";
    shelf.clear();
    std::cout << "end\n";
}

Q8. (short answer) Why does std::weak_ptr not change use_count()?

Q9. (design) A device farm must open a session, close it on every exit path, and forbid two jobs from holding the same session at once — while still allowing one job to hand its session to another. State which of the five special members you delete and which you keep, with a reason for each.

Q10. (analysis) Give two reasons shared_ptr is considered a last resort rather than the default owning pointer.


Scoring: mark yourself with the answers, then read the self-assessment guide.