Step 3 of 8
RAII
RAII stands for "Resource Acquisition Is Initialization". It's an awkward name for the most important idea in C++:
Tie every resource to an object. Acquire it in the constructor, release it in the destructor.
Because destructors always run when the object goes away, the resource is always released: on normal exit, early return, or an exception. You can't forget, and you can't get the order wrong. Memory, files, locks, network connections and database transactions are all managed this way.
new and delete
C++'s versions of malloc and free:
new T(args)creates one object on the heap and returns a pointer;delete pdestroys it.new T[n]creates an array;delete[] pdestroys it. Mixing them up (deleteon an array) is undefined behavior.new int[n](): the()zero-initializes the elements.
Unlike malloc, new runs constructors and delete runs destructors.
#include <iostream>
class Buffer {
public:
explicit Buffer(int n) : data_(new double[n]()), n_(n) {
std::cout << "allocated " << n_ << "\n";
}
~Buffer() {
delete[] data_;
std::cout << "freed " << n_ << "\n";
}
double& at(int i) { return data_[i]; }
int size() const { return n_; }
private:
double* data_;
int n_;
};
int main() {
Buffer b(3);
b.at(0) = 1.5;
b.at(2) = b.at(0) * 2;
std::cout << b.at(0) + b.at(1) + b.at(2) << "\n";
}
allocated 3
4.5
freed 3
main never calls delete. The Buffer owns its array and frees it in its destructor.
Returning a reference
double& at(int i) returns a reference to the element, so b.at(0) = 1.5 writes into the array. Returning double would return a copy, and the assignment would change the copy.
Your task
Finish IntArray: the destructor, plus int size() const, int& at(int i) (returns a reference so callers can write through it) and int sum() const.
Challenge 2
Finish Buffer, which owns a char array from new char[n]: the destructor, int size() const, void fill(char c) (every character becomes c), and std::string str() const (the characters as a string).
Challenge 3
RAII isn't just for memory. Write FileLog, which owns an open file: the constructor opens path for writing with std::fopen, bool ok() const says whether that worked, void write(const std::string& line) writes the line plus a newline, and the destructor closes the file. Closing is what makes sure everything reaches the disk.