落とし穴とライフタイム
ダングリングビューを避けます
「落とし穴とライフタイム」はCoddyKit上の無料C++ Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC++ Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C++ Academyコースには全4レッスンが含まれています。
ビューは所有しない
string_viewは、別の場所で所有されている文字を指すだけです。その記憶域がなくなると、ビューはダングリング状態になり、アクセスすると未定義動作になります。
一時オブジェクトによるダングリング
一時オブジェクトであるstd::stringにビューを束縛するのは危険です。一時オブジェクトは文の終わりで破棄されるため、ビューが解放済みメモリを指すことになります。
#include <string>
#include <string_view>
std::string make() { return "temp"; }
int main() {
std::string_view sv = make(); // dangles immediately
// using sv here is undefined behavior
(void)sv;
}ローカル変数へのビューを返す
ローカル文字列を指すビューを決して返さないでください。ローカル変数は関数が戻るときに破棄されます。
#include <string>
#include <string_view>
std::string_view bad() {
std::string local = "oops";
return local; // local dies, view dangles
}
int main() { (void)bad(); }安全な例: 存続中の文字列へのビュー
参照元がビューより長く存続する限り、ビューは安全です。この例では、文字列が関数全体の期間にわたって存続します。
#include <iostream>
#include <string>
#include <string_view>
int main() {
std::string s = "alive";
std::string_view sv = s;
std::cout << sv << "\n"; // safe
}null終端されていない
ビューのデータが\0で終わる保証はありません。sv.data()をC文字列を想定するC関数に渡すと、末尾を越えて読み取る可能性があります。
strlenではなくsize()を使う
ビューは大きなバッファーの一部をスライスしたものかもしれないため、長さにはC文字列関数ではなく、常にsv.size()を使用してください。
#include <iostream>
#include <string_view>
int main() {
std::string_view sv = std::string_view("hello world").substr(0, 5);
std::cout << sv.size() << "\n"; // 5, not 11
}参照元の変更
基になる文字列が再確保されると(たとえばpush_backによって容量が増える場合)、その文字列内を指していた既存のビューは無効になります。
メンバーへのビューの保存
string_viewをクラスメンバーとして保存する場合は注意してください。参照先のデータがオブジェクトより長く存続することを保証する必要があります。迷った場合は、代わりにstd::stringを保存してください。
パラメーターなら通常は安全
string_viewを関数パラメーターとして使用するのは、安全で慣用的なケースです。引数は関数呼び出しより長く存続するためです。
#include <iostream>
#include <string_view>
size_t len(std::string_view sv) { return sv.size(); }
int main() {
std::cout << len("temporary is fine here") << "\n";
}保持する必要があればコピーする
参照元のライフタイムを超えてテキストを保持する必要がある場合は、std::stringにコピーしてください。所有権を持つためのコストがコピーです。
#include <string>
#include <string_view>
std::string keep(std::string_view sv) {
return std::string(sv); // owns a copy
}
int main() { (void)keep("persist"); }経験則
パラメーターや短時間だけ使うローカル変数にはstring_viewを優先してください。データが明らかに長く存続する場合を除き、戻り値の型や長期間存続するメンバーとして使うのは避けてください。
理解度チェック
ビューのライフタイムについての理解度を確認しましょう。
まとめ
ビューの落とし穴とライフタイムについて学びました。
- ビューはデータを所有しないため、参照元はビューより長く存続する必要があります。
- 一時オブジェクトやローカル変数へのビューは避けてください。
- ビューはnull終端されている保証がないため、
size()を使用してください。 - テキストを保持する必要がある場合は、
std::stringにコピーしてください。
よくある質問
「落とし穴とライフタイム」レッスンは無料ですか?
はい。「落とし穴とライフタイム」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C++ Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C++ Academyコースには全4レッスンが含まれています。
「落とし穴とライフタイム」で何を学びますか?
ダングリングビューを避けます ブラウザで直接実行するハンズオンコードでC++ Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C++ Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC++ Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「落とし穴とライフタイム」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC++ Academyレッスンでコードを書いて実行できますか?
はい。すべてのC++ Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- string_viewを使う理由
- ビューの作成
- 落とし穴とライフタイム
- 文字列アルゴリズム