第41回 確認問題(スマートポインタ)
STEP 6 の RAII / unique_ptr / shared_ptr / weak_ptr の総合クイズ 12 問。
進め方
- 8 問以上正解で STEP 7(継承と多態)へ進める状態
- スマートポインタはモダン C++ の基本道具。苦手な型は該当章で復習を
RAII
RAII の哲学
0 / 2
Q1 リソース = 「取得したら解放が必要なもの」として該当しないのは?
ヒープメモリ
ファイルハンドル
ローカル変数の int
mutex ロック
ローカル変数の int はスタックから自動で消えるだけで特別な解放手続き不要。
Q2 「所有せず参照だけ渡したい」関数引数の適切な型は?
std::shared_ptr<T>
std::unique_ptr<T>
std::weak_ptr<T>
const T& または T*
参照や生ポインタが「借用」の自然な表現。shared_ptr での受け渡しは「所有権を共有する」という別の意図を持ってしまう。
unique
unique_ptr
0 / 3
Q3 unique_ptr を作る推奨形は?
std::unique_ptr<T> p(new T());
T* p = new T(); unique_ptr u(p);
auto p = std::make_unique<T>(args...);
std::unique_ptr p = T();
make_unique が推奨。型名の重複なし、例外安全性、シンプルさ。
Q4 unique_ptr をコピーしようとするとどうなる?
浅いコピーになる
コンパイルエラー
深いコピーになる
実行時エラー
unique_ptr はコピー禁止(= delete)。所有者が複数になる設計を言語レベルで禁止。std::move で所有権移動は可能。
Q5 unique_ptr を返す関数から呼び出し側へ何が起きる?
コピーされて性能が落ちる
生ポインタに変換される
ムーブか RVO で所有権が移る
参照カウントが増える
戻り値は右辺値なのでムーブ、または C++17 の RVO で省略されます。コピーは発生しません。
shared
shared_ptr
0 / 4
Q6 auto a = make_shared<int>(42); auto b = a; auto c = b; の後、a.use_count() は?
1
2
3
不定
a/b/c の 3 つが同じオブジェクトを共有しているので use_count は 3。
Q7 make_shared の利点は?
参照カウントが 0 から始まる
ヒープ確保が 1 回で済む
スレッドセーフになる
コピーが禁止される
オブジェクトと制御ブロックを同じメモリに確保するので、ヒープ確保が 1 回・キャッシュ効率も良い。
Q8 循環参照によるメモリリークの解決策は?
shared_ptr を全て unique_ptr に変更
すべての要素を vector に入れる
片方を weak_ptr にして循環を断ち切る
make_shared を使う
片方のリンクを weak_ptr にすれば参照カウントが増えないので循環が発生しません。所有者 → 子は shared、子 → 親は weak が定石。
Q9 まず検討するべきスマートポインタは?
shared_ptr(共有が基本)
unique_ptr(単独所有が基本)
weak_ptr
auto_ptr
所有者が 1 人で済む場合は unique_ptr を選ぶ。shared_ptr は参照カウントのオーバーヘッドがあり、本当に共有が必要な場合のみ。auto_ptr は C++17 で削除されました。
weak
weak_ptr
0 / 3
Q10 weak_ptr の特徴は?
所有権を持ち、参照カウントを増やす
コピー不可
所有権を持たず、参照カウントを増やさない
nullptr になれない
weak_ptr は「弱い参照」。use_count に影響せず、shared_ptr が破棄されれば自動的に expired 状態になります。
Q11 weak_ptr から中身にアクセスする正しい方法は?
*wp で直接
wp.lock() で shared_ptr を得てから
wp.get()
static_cast
weak_ptr はそのままではアクセスできません。lock() で一時的な shared_ptr を得て、空でないか確認してから使う。
Q12 ツリー構造で親子のリンクを設計するベストプラクティスは?
両方 shared_ptr
親 → 子は shared_ptr、子 → 親は weak_ptr
両方 weak_ptr
親 → 子は生ポインタ、子 → 親は unique_ptr
親が子を所有(shared)、子は親を参照だけ(weak)の組み合わせで循環参照を防ぎます。