#include <iostream>
#include <vector>
int main() {
std::cout << "Enter -1 to quit\n";
std::vector<int> items{97, 84, 72, 65};
std::cout << "Enter an index: ";
for (int print_index; std::cin >> print_index; ) {
if (print_index == -1) break;
std::cout << items.at(print_index) << '\n';
std::cout << "Enter an index: ";
}
}
#include <iostream>
#include <vector>
int main() {
std::cout << "Enter -1 to quit\n";
std::vector<int> items{97, 84, 72, 65};
std::cout << "Enter an index: ";
for (int print_index; std::cin >> print_index; ) {
if (print_index == -1) break;
try {
std::cout << items.at(print_index) << '\n';
items.resize(items.size() + 10);
} catch (const std::out_of_range& e) {
std::cout << "Index out of bounds\n";
} catch (...) {
std::cout << "Something else happened";
}
std::cout << "Enter an index: ";
}
}
try {
// Code that may throw an exception
} catch (/* exception type */) {
// Do something with the exception
} catch (...) { // any exception
// Do something with the exception
}
#include <iostream>
#include <vector>
int main() {
std::vector<int> items;
try {
items.resize(items.max_size() + 1);
} catch (std::bad_alloc& e) {
std::cout << "Out of bounds.\n";
} catch (std::exception&) {
std::cout << "General exception.\n";
}
}
(Extra reading for those interested)
#include <iostream>
class Giraffe {
public:
Giraffe() { std::cout << "Giraffe constructed" << '\n'; }
Giraffe(const Giraffe &g) { std::cout << "Giraffe copy-constructed" << '\n'; }
~Giraffe() { std::cout << "Giraffe destructed" << '\n'; }
};
void zebra() {
throw Giraffe{};
}
void llama() {
try {
zebra();
} catch (Giraffe g) {
std::cout << "caught in llama; rethrow" << '\n';
throw;
}
}
int main() {
try {
llama();
} catch (Giraffe g) {
std::cout << "caught in main" << '\n';
}
}
#include <iostream>
class Giraffe {
public:
Giraffe() { std::cout << "Giraffe constructed" << '\n'; }
Giraffe(const Giraffe &g) { std::cout << "Giraffe copy-constructed" << '\n'; }
~Giraffe() { std::cout << "Giraffe destructed" << '\n'; }
};
void zebra() {
throw Giraffe{};
}
void llama() {
try {
zebra();
} catch (const Giraffe& g) {
std::cout << "caught in llama; rethrow" << '\n';
throw;
}
}
int main() {
try {
llama();
} catch (const Giraffe& g) {
std::cout << "caught in main" << '\n';
}
}
try {
try {
try {
throw T{};
} catch (T& e1) {
std::cout << "Caught\n";
throw;
}
} catch (T& e2) {
std::cout << "Caught too!\n";
throw;
}
} catch (...) {
std::cout << "Caught too!!\n";
}
#include <iostream>
class Cake {
public:
Cake() : pieces_{8} {}
int getPieces() { return pieces_; }
Cake& operator--() { --pieces_; }
private:
int pieces_;
};
int main() {
try {
try {
try {
throw Cake{};
} catch (Cake& e1) {
--e1;
std::cout << "e1 Pieces: " << e1.getPieces() << " addr: " << &e1 << "\n";
throw;
}
} catch (Cake e2) {
--e2;
std::cout << "e2 Pieces: " << e2.getPieces() << " addr: " << &e2 << "\n";
throw;
}
} catch (Cake& e3) {
--e3;
std::cout << "e3 Pieces: " << e3.getPieces() << " addr: " << &e3 << "\n";
}
}
void g() {
throw std::runtime_error{""};
}
int main() {
auto ptr = new int{5};
g();
// Never executed.
delete ptr;
}
void g() {
throw std::runtime_error{""};
}
int main() {
auto ptr = std::make_unique<int>(5);
g();
}
Not safe
Safe
Resource acquisition is initialisation
A concept where we encapsulate resources inside objects
eg. Memory, locks, files
Every resource should be owned by either:
Another resource (eg. smart pointer, data member)
The stack
A nameless temporary variable
#include <exception>
class MyInt {
public:
MyInt(int i) : i_{i} {
if (i == 2) throw std::exception();
}
private:
int i_;
};
class UnsafeClass {
public:
UnsafeClass(int a, int b):
a_{new MyInt{a}}, b_{new MyInt{b}} {}
~UnsafeClass() {
delete a_;
delete b_;
}
private:
MyInt* a_;
MyInt* b_;
};
int main() {
UnsafeClass a{1, 2};
}
Spot the bug
#include <exception>
#include <memory>
class MyInt {
public:
MyInt(int i) : i_{i} {
if (i == 2) throw std::exception();
}
private:
int i_;
};
class UnsafeClass {
public:
UnsafeClass(int a, int b):
a_{std::make_unique<MyInt>(a)},
b_{std::make_unique<MyInt>(b)} {}
private:
std::unique_ptr<MyInt> a_;
std::unique_ptr<MyInt> b_;
};
int main() {
UnsafeClass a{1, 2};
}
class S {
public:
int foo() const; // may throw
}
class S {
public:
int foo() const noexcept; // does not throw
}