提案されたC++ライブラリ を模倣するように設計された内部ライブラリを使用しており、過去数年の間にstd::string
〜string_view
。
新しいインターフェイスに準拠するように、コードを忠実に変更します。残念ながら、私が渡さなければならないのはstd :: stringパラメータと、std :: string戻り値であるものです。だから私のコードは次のようなものから変更されました:
void one_time_setup(const std::string & p1, int p2) {
api_class api;
api.setup (p1, special_number_to_string(p2));
}
に
void one_time_setup(const std::string & p1, int p2) {
api_class api;
const std::string p2_storage(special_number_to_string(p2));
api.setup (string_view(&p1[0], p1.size()), string_view(&p2_storage[0], p2_storage.size()));
}
私は本当にこの変更がAPIクライアントとして私に何をもたらしたのか、(たぶん台無しにするために)より多くのコードを除いてわかりません。 API呼び出しは安全性が低く(APIがパラメーターのストレージを所有しなくなったため)、おそらくプログラム0の作業を保存し(最適化を移動するコンパイラーが今すぐ実行できるため)、それが作業を保存したとしても、それだけです起動後に、またはどこかで大きなループで実行されない、または実行されないいくつかの割り当て。このAPIでは使用できません。
ただし、このアプローチは、たとえば this answer のように、他の場所で見られるアドバイスに従っているようです。
余談ですが、C++ 17以降では、std :: string_viewを優先してconst std :: string&を渡すことは避けてください。
主に最適化を目的として、比較的安全なオブジェクトを安全性の低いオブジェクト(基本的には美化されたポインタと長さ)に普遍的に置き換えることを提唱しているように思われるため、このアドバイスは驚くべきものです。
それで、string_viewをいつ使用するべきか、いつ使用すべきではないのですか?
std::string
(非定数、非参照)を使用してください。このオプションでは、値が呼び出しコンテキストで再び使用されないことがわかっている場合は、値を明示的に移動することもできます。std::string_view
(const、non-ref)を使用してください。これは、string_view
がstd::string
とchar*
を問題なく簡単に処理でき、コピーを作成しないためです。これにより、すべてのconst std::string&
パラメータが置き換えられます。最終的には、あなたのようにstd::string_view
コンストラクターを呼び出す必要がない決して必要はありません。 std::string
には、変換を自動的に処理する 変換演算子 があります。
std::string_view
はconst char*
のいくつかの利点をC++にもたらします:std::string
とは異なり、string_view
std::string&
よりも1レベル少ないポインター間接参照を持っています。つまり、string_viewは、生のポインタを処理する必要なく、コピーを回避できることがよくあります。
最近のコードでは、std::string_view
はconst std::string&
関数パラメーターのほぼすべての使用を置き換える必要があります。 std::string
は変換演算子をstd::string_view
に宣言しているため、これはソース互換の変更である必要があります。
文字列ビューが役に立たないからといって特定の使用例ではとにかく文字列を作成する必要がある場所は、それが一般的に悪い考えであることを意味しません。 C++標準ライブラリは、利便性よりも一般性のために最適化される傾向があります。自分で文字列ビューを作成する必要はないはずなので、「安全性が低い」という議論は成り立ちません。
主に最適化を目的として、比較的安全なオブジェクトを安全性の低いオブジェクト(基本的には美化されたポインタと長さ)に普遍的に置き換えることを提唱しているように思われるため、このアドバイスは驚くべきものです。
これはこの目的を少し誤解していると思います。これは「最適化」ですが、std::string
を使用する必要がないように自分自身を解き放つと考える必要があります。
C++のユーザーは、さまざまな文字列クラスの数十を作成しています。固定長の文字列クラス、テンプレートサイズがバッファサイズであるSSO最適化クラス、それらを比較するために使用されるハッシュ値を格納する文字列クラスなど。COWベースの文字列を使用する人もいます。 C++プログラマがやりたいことが1つあるとすれば、それは文字列クラスを書くことです。
また、Cライブラリによって作成および所有される文字列は無視されます。裸のchar*
s、おそらくある種のサイズ。
したがって、いくつかのライブラリを作成していて、const std::string&
を取得する場合、ユーザーは使用していた文字列を取得してstd::string
にコピーする必要があります。たぶん何十回も。
std::string
の文字列固有のインターフェイスにアクセスする必要がある場合、なぜcopy文字列にする必要がありますか?それはそのような無駄です。
パラメータとしてstring_view
を使用しない主な理由は次のとおりです。
最終的な目標が、NULで終了する文字列(fopen
など)を受け取るインターフェイスに文字列を渡すことである場合。 std::string
は、NULで終了することが保証されています。 string_view
は違います。また、ビューを部分文字列にしてNULで終了しないようにするのは非常に簡単です。 std::string
を部分文字列化すると、部分文字列がNULで終了する範囲にコピーされます。
私は、まさにこのシナリオのために、特別なNULで終了するstring_viewスタイルのタイプを書きました。ほとんどの操作を実行できますが、NUL終了ステータス(たとえば、最後からトリミング)を壊す操作は実行できません。
生涯の問題。本当にstd::string
をコピーする必要がある場合、または文字配列を関数呼び出しよりも長く有効にする必要がある場合は、const std::string &
を使用して、このことを前もって述べるのが最善です。または、単にstd::string
を値パラメーターとして使用します。そうすれば、そのような文字列がすでにある場合は、すぐにその所有権を主張できます。呼び出し側は、文字列のコピーを保持する必要がない場合は、その文字列に移動できます。