参照の寿命とダングリング参照
オブジェクトの寿命を慎重に考え、ダングリング参照を避けます。
「参照の寿命とダングリング参照」はCoddyKit上の無料C++ Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC++ Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C++ Academyコースには全4レッスンが含まれています。
ダングリング参照とは何か
参照先のオブジェクトが破棄されると、参照はダングリング状態になります。それを使用すると未定義動作となり、何が起こるか分かりません。
典型的な例
ローカル変数への参照を返すケースです。関数が戻るとローカル変数は破棄され、呼び出し元は破棄済みのメモリへの参照を保持することになります。
// BUG
int& bad() {
int x = 10;
return x; // x dies here
}
int& r = bad();
std::cout << r; // UBコンテナ要素への参照
std::vectorが再割り当てを行うと、vector内の要素への参照はダングリング参照になります。要素を追加すると、すべての格納領域が移動する可能性があります。
std::vector<int> v = {1, 2, 3};
int& r = v[0];
v.push_back(99); // may reallocate
std::cout << r; // possibly UBマップとリストへの参照
一部のコンテナ(std::list、std::map、影響を受けないノードに対するstd::unordered_map)は、無効化されにくいイテレーターと参照を提供します。std::vectorとstd::dequeは提供しません。
一時オブジェクトの寿命規則
const参照は一時オブジェクトの寿命を延長します。ただし、その参照を返す関数がさらに寿命を延長することはありません。
// Subtle BUG
const std::string& f() {
return std::string("temp"); // dies at return
}
const std::string& s = f(); // danglingif-init文での寿命(C++17)
C++17のif/switch初期化文で宣言した変数は、if/switch本体が終わるまで存続します。便利な機能ですが、スコープを意識してください。
if (const auto& it = map.find(k); it != map.end()) {
use(it->second);
}
// `it` is dead hereクラスの参照メンバー
参照をクラスメンバーとして格納すると、クラスの寿命が参照先に結び付けられます。クラスが参照先より長く存続することはできません。所有権の意味上必要な場合に限って使用してください。
所有が省略可能な場合のポインターと参照
参照はnullになりませんが、参照先が破棄されると参照は壊れます。所有が省略可能な場合やダングリングの可能性がある場合は、ポインターのほうが意図を明確に表現できます。
代わりにスマートポインターを使う
共有所有権にはstd::shared_ptrを使用してください。少なくとも1つのshared_ptrが存在する間、ポインターがオブジェクトを存続させます。詳しくはスマートポインターのコースで扱います。
コンパイラーの支援:lifetimebound
最新のコンパイラー(Clang、GCC)は、一部のダングリング参照パターンに対して警告を出します。利用可能な場合は-Wdangling-referenceを有効にしてください。
よく使われるイディオム:ビュー型
std::string_viewとstd::spanは、所有権を持たないビューです。参照と同じ寿命に関する注意点があり、同じように慎重に扱う必要があります。
確認問題
std::vector内の要素への参照を無効にする可能性がある操作はどれですか。
まとめ
参照は何かを所有したり寿命を延長したりせず、既存のオブジェクトの別名になるだけです。オブジェクトが先に破棄されると、参照はダングリング参照になります。ローカル変数への参照の返却、コンテナの再割り当て、長く残る一時オブジェクトには注意してください。
よくある質問
「参照の寿命とダングリング参照」レッスンは無料ですか?
はい。「参照の寿命とダングリング参照」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C++ Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C++ Academyコースには全4レッスンが含まれています。
「参照の寿命とダングリング参照」で何を学びますか?
オブジェクトの寿命を慎重に考え、ダングリング参照を避けます。 ブラウザで直接実行するハンズオンコードでC++ Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C++ Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC++ Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「参照の寿命とダングリング参照」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC++ Academyレッスンでコードを書いて実行できますか?
はい。すべてのC++ Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 変数の別名となる参照の理由
- 値渡しと参照渡しの比較
- const参照とその使いどころ
- 参照の寿命とダングリング参照