C++レビュー|ヒープとスタックの使い分け基準と設計レビュー観点整理
この記事のポイント
- ヒープとスタックの使い分け設計をレビューアーが読み解く技術を整理
 - 寿命責務・所有権・パフォーマンスの設計判断をレビュー視点で解説
 - new/delete露出の是非を読み取るレビュー力を養う
 
そもそもヒープとスタックとは
C++におけるメモリ配置は大きく次の2種類に分類できます。
| 領域 | 特徴 | 
|---|---|
| スタック | 自動変数、関数スコープ依存、自動解放、高速、容量制限 | 
| ヒープ | new/delete管理、寿命自由、手動解放必要、断片化注意 | 
比較ポイント整理
- 寿命:スタックはスコープ従属、ヒープは自由
 - 速度:スタックは非常に高速(ポインタ加算のみ)
 - 安全性:スタックは自然解放、ヒープは解放漏れリスク
 - 容量:ヒープは大容量可能、スタックは上限制約あり
 
レビューアーは「なぜこの配置選択が採用されたのか?」を静的に読み取ります。
なぜこれをレビューするのか
ヒープ/スタックの使い分けは設計全体の保守性・安全性・パフォーマンスに直結します。
- ヒープ不要な場面でのnew多用 → 解放責務分散
 - スタックで巨大オブジェクト確保 → スタックオーバーフロー事故
 - 寿命誤読によるuse-after-free発生
 
レビュー段階で
寿命と所有権を静的に読み解く習慣が最重要です。
レビューアー視点
- 寿命管理をスコープ管理で吸収できるか確認
 - ヒープ配置は解放責任が集中しているか確認
 - new露出が不要でないか静的に評価
 - サイズ・容量をスタック制約に合わせて整理できるか確認
 - 例外安全性を構造保証できるか評価
 
開発者視点
- まずスタック前提で設計を考える
 - サイズ超過や寿命要件で必要時のみヒープ選択
 - ヒープ採用時はRAIIを前提に責務集中
 - コンテナ活用で動的寿命管理を構造吸収
 
良い実装例
想定:APIリクエストログのスタック集中モデル
良い設計例
#include <string>
#include <iostream>
struct ApiRequestLog {
    int requestId;
    std::string endpoint;
    std::string clientIp;
    int responseCode;
    time_t requestedAt;
};
void process() {
    ApiRequestLog log {
        1001, "/api/items", "192.168.0.10", 200, std::time(nullptr)
    };
    std::cout << log.requestId << std::endl;
}良いポイント
- スタック上の自動変数で寿命管理
 - スコープ終了で自動解放
 - new/delete完全排除
 - 例外安全自然保証
 
レビュー観点
- newが必要な場面か?(不要new排除)
 - スタックサイズ内に収まる設計か
 - RAIIによる自動解放構造に寄せられているか
 - ヒープ採用時は所有権集中・RAII統合できているか
 - API契約に解放責務を転嫁していないか
 - 例外発生時にも安全か
 
良くない実装例: ケース1(不要new使用)
問題例①
void process() {
    ApiRequestLog* log = new ApiRequestLog();
    log->requestId = 1001;
    std::cout << log->requestId << std::endl;
    delete log;
}
@Reviewernew/deleteを使用する必要がありません。スタック自動変数で寿命管理してください。RAII構造に統一しましょう。
改善例
改善例①
ApiRequestLog log {1001, "/api/items", "192.168.0.10", 200, std::time(nullptr)};良くない実装例: ケース2(巨大スタック構造)
問題例②
void process() {
    char buffer[10 * 1024 * 1024];  // 10MBスタック確保
}
@Reviewerスタック容量超過リスクがあります。巨大バッファはヒープ(std::vector等)管理へ移行してください。
改善例
改善例②
std::vector<char> buffer(10 * 1024 * 1024);良くない実装例: ケース3(寿命管理の分散)
問題例③
class LogSession {
public:
    void start() {
        log_ = new ApiRequestLog();
    }
    void end() {
        delete log_;
    }
private:
    ApiRequestLog* log_;
};
@Reviewernew/deleteはRAII構造で集中管理してください。unique_ptr管理に移行しましょう。end()自体が不要になります。
改善例
改善例③
class LogSession {
public:
    LogSession() : log_(std::make_unique<ApiRequestLog>()) {}
private:
    std::unique_ptr<ApiRequestLog> log_;
};観点チェックリスト
まとめ
ヒープ/スタックレビューは
「寿命責任がスコープに埋め込めるかを読み取るレビュー」です。
レビューアーは常に
- newを使わずに済ませられないか?
 - 巨大オブジェクトは安全に管理できているか?
 - 解放責務は自然解放構造に吸収されているか?
 
を静的に読み取り、寿命集中+安全領域設計へ誘導するのが役割です。
