<aside> đź’ˇ Exception Safety

<aside> 💡 Specifically, 3 levels of exn safety for a f’n f:

  1. Basic guarantee
  2. Strong guarantee
  3. No-throw guarantee
class A {...};
class B {...};
class C {
	A a;
	B b;
	public:
	void f() {
		a.g(); // may throw (strong guarantee)
		b.h(); // may throw (strong guarantee)
	}
}

Is C::f exn safe?

thus: no, probably not exn safe

If A::a and B::h do not have non-local side effects, can use copy + swap:

class C {
	...
	void f() {
		A atemp = a;
		B btemp = b;
		atemp.g();
		btemp.h();
// ↑ If those throw, original a + b still intact(無傷)
		a = atemp;
		b = btemp;
// ↑ But what if copy assignment throw?
// In particular what if a a=atemp succeed, but b=btemp fails?
	}
};

Better if swap was no throw.

Recall: copying ptrs can’t throw

struct CImpl {
	A a;
	B b;
};
class C {
	unique.ptr<CImpl> pImpl;
	void f() {
		auto tmp = make.unique<CImpl>(* pImpl);
		temp->a.g();
		temp->b.h();
		std::swap(pImpl, tmp); // no-throw
	}
};
// If either A::g or B::b offer no exn safety guarantee,
// then neither can f

<aside> đź’ˇ Exception Safety of STL - vector

vectors

void f() {
	vector<c> v;
	...
}
// v goes out of scope, array is freed,
// C's dtor runs for all objects in v

But…

void g() {
	vector<c*> v;
	...
// array is freed, ptrs don't have dtors,
// and objs ptd to by the ptrs are NOT deleted
// no explicit deallocation
}

</aside>

<aside> đź’ˇ vector<c> - owns the objs

vector<c*> - does not own the objs

vector<unique.ptr<c>> - owns the objs

vector<T>::emplace.back - offers the strong guarantee

If the move ctor offer the nothrow guarantee, emplace_back will use the move ctor. Otherwise, it will use the copy ctor, which may be slower

class C {
	public:
	C(C &&other) noexcept {...}
	C &operator=(C &&other) noexcept {...}
};

If you know a f’n will never throw or propagate an exn, declare if noexcept. Facilitates optimization At minimam: moves & swaps should be noexcept

<aside> đź’ˇ Casting

In C

Node n;
int *ip = (int *) &n; // const-forces C++ to treat a Node* as an int*

<aside> đź’ˇ If you must const, use a C++ - style cast:

  1. Static.cast - “sensible casts” - casts with a well-defined semantics eg. double -> int

    double d;
    void f(int x);
    void f(double d);
    f(static_cast<int>(d)); // calls void f(int x);
    

    eg. superclass ptr → subclass ptr

    Book *b = new Text {...};
    Text *t = static.cast<Text*>(b);
    

</aside>

</aside>