C++レビュー|std::array使用場面の設計判断とレビュー観点整理
この記事のポイント
- std::arrayをレビューアーがどのように読み解くべきか整理
- vectorと使い分けるための設計判断基準を解説
- 固定長配列設計における責務集中レビューを習得
そもそもstd::arrayとは
C++11から導入された std::array
は固定長安全配列を表現する標準コンテナです。
std::array<int, 10> arr{};
裸配列(raw array)の以下の問題を解消します。
- サイズ情報の失伝
- 配列長の静的管理
- 所有権責務の曖昧さ
- スコープ自動解放の欠如
std::array
は 固定長でありながら、安全性と所有権集中が得られる という位置づけです。
std::arrayの特徴整理
- サイズはコンパイル時固定
- スコープ管理で例外安全が保証される
- 生配列と違いコピー・代入が可能
- C配列APIとのブリッジも可能(.data()利用)
レビューアーはvectorとの違いを理解しながら、適切な使用場面を判定する役割を担います。
なぜこれをレビューするのか
固定長配列なのに裸配列を残している実装は依然多く残ります。
以下のような問題が継続します。
- 境界外アクセスの静的検出困難
- delete[]責務の分散
- サイズ長の分散管理
- 保守性の低下
レビュー段階でstd::array移行を提案することで、固定長構造の安全性が飛躍的に向上します。
レビューアー視点
- サイズ固定配列の設計意図を読み解く
- std::array移行可能箇所を洗い出す
- 所有権責務がスコープに集約されているか確認
- vectorとの使い分け理由を設計から読み取る
開発者視点
- 固定長なら常にstd::arrayを第一候補に置く
- スコープに基づく自動解放設計に寄せる
- 生配列API境界部だけ裸配列併用
- vectorとの役割分担を整理
良い実装例
想定:APIリクエストの固定バッファ保持
良い設計例
#include <array>
#include <string>
#include <iostream>
struct ApiRequestLog {
int requestId;
std::string endpoint;
std::string clientIp;
int responseCode;
time_t requestedAt;
};
class LogBuffer {
public:
static constexpr size_t capacity = 10;
void add(const ApiRequestLog& logEntry, size_t index) {
if (index >= logs_.size()) {
throw std::out_of_range("Index out of range");
}
logs_[index] = logEntry;
}
void dump() const {
for (const auto& log : logs_) {
std::cout << log.requestId << std::endl;
}
}
private:
std::array<ApiRequestLog, capacity> logs_;
};
良いポイント
- サイズ固定をコンパイル時に保証
- delete[]責務不要
- 例外安全保証
- 境界外アクセスを防御可能
レビュー観点
- 裸配列使用箇所をstd::arrayへ移行できているか
- サイズ固定意図が設計から読み取れるか
- delete[]責務が完全排除されているか
- スコープでライフサイクル集中管理されているか
- 境界外アクセスが構造防止されているか
- vectorとの使い分け方針が明示されているか
良くない実装例: ケース1(固定長裸配列維持)
問題例①
void process() {
ApiRequestLog logs[10];
logs[0].requestId = 1;
}
@Reviewer固定長配列はstd::arrayへ移行してください。サイズ管理を型レベルで埋め込み、裸配列による境界外アクセスリスクを排除しましょう。
問題点
- サイズ管理が外部に分散
- 型安全性が低い
- 境界違反検出が困難
改善例
改善例①
std::array<ApiRequestLog, 10> logs{};
logs[0].requestId = 1;
良くない実装例: ケース2(動的確保で固定長を模倣)
問題例②
ApiRequestLog* logs = new ApiRequestLog[10];
logs[0].requestId = 1;
delete[] logs;
@Reviewer固定長意図ならstd::arrayへ移行してください。動的確保の必要はなく、所有権をスコープ管理で集中できます。
問題点
- delete[]責務残存
- 例外安全性欠如
- 所有権が読み取れない
改善例
改善例②
std::array<ApiRequestLog, 10> logs{};
logs[0].requestId = 1;
良くない実装例: ケース3(API契約に裸配列露出)
問題例③
void save(ApiRequestLog logs[10]) {
for (size_t i = 0; i < 10; ++i) {
std::cout << logs[i].requestId << std::endl;
}
}
@ReviewerAPI契約もstd::array受取に変更してください。サイズ管理責務を型レベルに吸収し、呼び出し側の契約負担を軽減しましょう。
改善例
改善例③
void save(const std::array<ApiRequestLog, 10>& logs) {
for (const auto& entry : logs) {
std::cout << entry.requestId << std::endl;
}
}
観点チェックリスト
まとめ
std::arrayレビューは
「裸配列排除+固定長責務集中」 という安全設計レビューです。
レビューアーは常に
- サイズ固定なら裸配列でなくstd::arrayで設計しているか?
- 型情報で契約を明示化しているか?
- delete[]が設計から消滅しているか?
を読み取り、所有権集中+スコープ安全な設計 へ誘導することが重要になります。