私は、少なくとも最良のシナリオ以上のプログラムを作成しようとする駆け出しのプログラマーです。私は Herb Sutter の「Exceptional C++」を読んでおり、これまでに例外安全性の章を 3 回読みました。ただし、彼が提示した例 (スタック) を除いて、例外の安全性と速度を正確に比較する必要がある時期と、そうするのがばかげている時期はよくわかりません。
たとえば、私の現在の宿題プロジェクトは二重リンク リストです。すでにこれらのいくつかをプログラムしたので、時間をかけて ES などのより深い概念に取り掛かりたいと思いました。
これが私のポップフロント機能です:
void List::pop_front()
{
if(!head_)
throw std::length_error("Pop front: List is empty.\n");
else
{
ListElem *temp = head_;
head_ = head_->next;
head_->prev = 0;
delete temp;
--size_;
}
}
これにはいくつかのジレンマがありました。
1) リストが失敗した場合、本当にエラーをスローする必要がありますか? リストのユーザーに try {] catch() {} ステートメント (これも遅い) を強制的に実行させるのではなく、単純に何もせずに戻るべきではないでしょうか。
2) 複数のエラー クラスがあります (さらに、クラスに実装することを先生が要求する ListException もあります)。カスタムエラークラスは本当に必要ですか?特定の例外クラスをいつ使用するかについての一般的なガイドはありますか? (たとえば、範囲、長さ、境界はすべて同じように聞こえます)
3) 例外をスローしたすべてのコードが完了するまで、プログラムの状態を変更してはならないことを知っています。これが、size_last をデクリメントしている理由です。この単純な例では、これは本当に必要ですか? delete がスローできないことはわかっています。0 に割り当てたときに head_->prev がスローされることはありますか? (頭は最初のノードです)
私の push_back 関数:
void List::push_back(const T& data)
{
if(!tail_)
{
tail_ = new ListElem(data, 0, 0);
head_ = tail_;
}
else
{
tail_->next = new ListElem(data, 0, tail_);
tail_ = tail_->next;
}
++size_;
}
1) C++ プログラムでは何でも失敗する可能性があるとよく耳にします。ListElem のコンストラクターが失敗するかどうか (または ing 中に tail_ が失敗new
するかどうか) をテストするのは現実的ですか?
2) 型が構造に対して実行可能であることを確認するために、データの型をテストする必要がありますか (現在、typedef int T
すべてをテンプレート化するまでは単純です)。
これらは非常に単純な例であることは理解していますが、実際に優れた ES を実践する必要がある場合とそうでない場合について、現在混乱しています。