We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← References, Pointers, Ownership step 3 of 4
Give an allocated object an owner
When an object needs dynamic allocation and a single owner, std::unique_ptr
can manage its lifetime. The owner destroys the object when it is reset or
destroyed, including when a normal return or exception leaves its scope.
Ownership can also move to another unique pointer.
Dynamic allocation is a design choice. Returning an object by value or using a base-class reference does not, by itself, require a heap allocation.
std::unique_ptr<Shape> make_shape(int kind, int a, int b); // returns ownership
void consume(std::unique_ptr<Shape> shape); // takes ownership
void inspect(const Shape& shape); // borrows an object
A unique pointer can be null and cannot be copied. It has no shared reference count. Its representation depends on its pointer and deleter types, so do not assume every specialization has the same size as a raw pointer. The pointed-to object is stored separately from the unique pointer itself.
Establish ownership before checking for rejection
This pattern can leak:
Shape* shape = new Rect(a, b);
if (shape->area() <= 0) {
return nullptr; // shape has no owner to delete it
}
return std::unique_ptr<Shape>(shape);
Give the object an owner before taking a path that might return early:
auto shape = std::make_unique<Rect>(a, b);
if (shape->area() <= 0) {
return nullptr; // the local owner destroys the rejected rectangle
}
return shape; // transfers ownership to the returned pointer
make_unique allocates and constructs the object, then returns its owner.
It does not construct the object inside the unique pointer. Direct construction
such as std::unique_ptr<Rect>(new Rect(a, b)) also establishes ownership in
one expression; the starter's bug is the separate rejection branch before
adoption. Prefer make_unique for ordinary construction. Adopting an existing
allocation or using a custom deleter can require a different constructor.
Observing, resetting and transferring
| Operation | Effect |
|---|---|
p.get() |
Borrow the stored pointer without changing ownership |
p.reset() |
Destroy the owned object, if any, and become null |
p.release() |
Return the pointer and become null without destroying the object |
auto q = std::move(p); |
Move ownership into q; p becomes null |
std::move(p) alone is a cast; the receiving move operation transfers ownership.
Do not delete a pointer obtained from get() while its unique pointer still
owns it. After release(), arrange a new owner or the correct cleanup operation;
that may be a custom deleter rather than delete.
This task returns derived objects through std::unique_ptr<Shape> using its
default deleter. Shape therefore has a virtual destructor so deleting through
the base pointer also destroys the derived object correctly.
Your task
std::unique_ptr<Shape> make_shape(int kind, int a, int b);
| Kind | Construct |
|---|---|
1 |
Rect(a, b), whose area is a * b |
2 |
Square(a), whose area is a * a; ignore b |
| Any other value | Return nullptr |
Reject a constructed shape if its area is zero or negative. The rule checks
the computed area, not each dimension: for example, Square(-3) has area 9
and is accepted. Inputs keep the area calculations within the range of int.
Leave Shape, its derived classes and audit unchanged. The provided audit
function reports one area per specification (-1 for rejection), followed by
how many accepted shapes meet its threshold. The harness then reports
Shape::live after all local owners have been destroyed. It must be zero,
including when a shape is rejected.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
C++ reference solution
Sign in to track your attempts toward unlocking the reference solution.