導入
C++で開発を行っていると、「特定のクラスのコピーを禁止したい」「特定の型での関数呼び出しを拒否したい」という場面に遭遇します。かつてはprivate領域に宣言のみを記述する手法が一般的でしたが、C++11以降は = delete 構文を使うことで、より直感的かつ安全に意図をコードへ組み込めるようになりました。本記事では、この構文がなぜ重要なのか、そして実務でどのように活用すべきかを解説します。
基礎知識
= delete は、関数定義の代わりに記述することで、その関数の使用を「削除(禁止)」する機能です。この関数が呼び出された場合、コンパイラは即座にエラーを吐き出します。
重要な点は、単に「呼び出しを止める」だけでなく、「コンパイルエラーによって開発者に誤用を早期に気付かせる」という点にあります。これにより、実行時の予期せぬ動作を未然に防ぎ、堅牢なクラス設計を実現します。
実装/解決策
実務で最も頻出するケースは「コピー不可クラス」の作成です。また、テンプレート関数において「特定の型だけ処理させたくない」という場合にも極めて有効です。
基本的には、禁止したい関数の宣言末尾に = delete を記述するだけで完了します。
サンプルプログラム
以下のコードは、コピーを禁止したクラスと、特定の型を受け付けない汎用関数の実装例です。
include
include
// シングルトンやリソース管理クラスなどでよく使われる「コピー禁止」の例
class DatabaseConnection {
public:
DatabaseConnection() = default;
// コピーコンストラクタと代入演算子を禁止
DatabaseConnection(const DatabaseConnection&) = delete;
DatabaseConnection& operator=(const DatabaseConnection&) = delete;
};
// テンプレート関数で、特定の型(doubleなど)を明示的に拒否する例
template
void processValue(T value) {
std::cout << "処理中: " << value << std::endl;
}
// double型での呼び出しを禁止する(コンパイルエラーになる)
void processValue(double) = delete;
int main() {
DatabaseConnection db1;
// DatabaseConnection db2 = db1; // コマンドアウトを外すとコンパイルエラーになります
processValue(10); // OK: intは許可
// processValue(3.14); // エラー: doubleはdeleteされているため禁止
return 0;
}
応用・注意点
実務における注意点は以下の2点です。
1. エラーメッセージの活用
= delete を活用すると、コンパイラが「deleted function」という明確なメッセージを出力するため、なぜその呼び出しがNGなのかを他のエンジニアが容易に理解できます。ドキュメントを読み込む手間を省けるという副次的効果もあります。
2. デフォルトの挙動との兼ね合い
デストラクタを = delete にすると、そのクラスのオブジェクトをスタック領域に確保できなくなります(メモリ解放ができないため)。また、ムーブ演算子とコピー演算子の関係など、特殊メンバ関数をdeleteする際は、C++のルール(Rule of Zero/Five)を意識し、意図しない暗黙的な削除が発生していないか確認することが重要です。
設計の意図をコンパイラに伝えることで、コードの安全性は飛躍的に向上します。ぜひ積極的に活用してください。

コメント