ProgrammingC++開発者

C++11における三の法則(Rule of Three)と五の法則(Rule of Five)について説明し、クラス設計における重要性を述べてください。

Hintsage AIアシスタントで面接を突破

答え。

三の法則: クラスがリソース(例えばメモリ)を管理する場合、次のいずれかのメソッドを明示的に実装する場合、残りも実装する必要があります:

  • デストラクタ
  • コピーコンストラクタ
  • コピー代入演算子

C++11: 五の法則 – 移動操作が追加されました:

  • 移動コンストラクタ
  • 移動代入演算子

このルールを破ると、ダブル削除やメモリリークなどのリソース管理のエラーが発生する可能性があります。

コード例:

class Buffer { char* data; public: Buffer(size_t sz) : data(new char[sz]) {} ~Buffer() { delete[] data; } Buffer(const Buffer& other) : data(new char[strlen(other.data)+1]) { strcpy(data, other.data); } Buffer& operator=(const Buffer& other) { if (&other != this) { delete[] data; data = new char[strlen(other.data)+1]; strcpy(data, other.data); } return *this; } // C++11以降のムーブセマンティクス: Buffer(Buffer&& other) noexcept : data(other.data) { other.data = nullptr; } Buffer& operator=(Buffer&& other) noexcept { if (&other != this) { delete[] data; data = other.data; other.data = nullptr; } return *this; } };

トリック質問。

クラスがポインタを管理する場合、デストラクタだけを実装すれば十分ですか?

いいえ。コピーと移動の操作がない場合、コピー時にメモリの二重削除が発生します。例:

Buffer a(10); Buffer b = a; // bとaは同じポインタを削除します!

このトピックの詳細を知らなかったための実際のエラーの例。


ストーリー

通信データ集約プラットフォームでは、すべてのクラスでデストラクタのみを実装していました。構造のリファクタリング後、ダブルフリーによる大規模なクラッシュが発生しました: オブジェクトのコピーがランダムな動作を引き起こしました。


ストーリー

モバイルゲームプロジェクトでは、バッファのコンテナクラスにムーブコンストラクタを実装し忘れました。移動時にオブジェクトがコピーされ、データの余分なコピーとパフォーマンスの低下が発生しました。


ストーリー

データ構造のシリアライゼーションライブラリでは、関数からオブジェクトを返す際に、一時オブジェクトが返され、コピーコンストラクタがポインタの浅いコピーを作成していました。何ヶ月も経ってから現れた多くのメモリリークが発生しました。