[解決済み] std::string` の部分文字列に対する `string_view` を効率的に取得する方法
質問
使用方法 http://en.cppreference.com/w/cpp/string/basic_string_view を参照すると、これをよりエレガントに行う方法が見当たりません。
std::string s = "hello world!";
std::string_view v = s;
v = v.substr(6, 5); // "world"
さらに悪いことに、この素朴なアプローチは落とし穴であり、そのために
v
へのダングリングリファレンスが残ります。
std::string s = "hello world!";
std::string_view v(s.substr(6, 5)); // OOPS!
I 覚えているようだ 標準ライブラリに、部分文字列をビューとして返す機能が追加されるかもしれない、というようなことを思い出した。
auto v(s.substr_view(6, 5));
以下のような回避策が考えられます。
std::string_view(s).substr(6, 5);
std::string_view(s.data()+6, 5);
// or even "worse":
std::string_view(s).remove_prefix(6).remove_suffix(1);
正直なところ、これらのどれもがあまり良いとは思えません。今考えられる最善のことは、エイリアスを使用して、物事を単純に冗長でなくすることです。
using sv = std::string_view;
sv(s).substr(6, 5);
どのように解決するのですか?
フリーファンクションのルートもありますが
std::string
のオーバーロードも提供しない限り、蛇足になる。
#include <string>
#include <string_view>
std::string_view sub_string(
std::string_view s,
std::size_t p,
std::size_t n = std::string_view::npos)
{
return s.substr(p, n);
}
int main()
{
using namespace std::literals;
auto source = "foobar"s;
// this is fine and elegant...
auto bar = sub_string(source, 3);
// but uh-oh...
bar = sub_string("foobar"s, 3);
}
IMHOでは、string_viewの全体のデザインは、私たちをセグメンテーション違反と怒れる顧客の世界に連れ戻すようなホラーショーです。
を更新しました。
のオーバーロードを追加しても
std::string
のオーバーロードを追加するだけでもホラーショーです。微妙なセグメンテーションの時限爆弾を見つけられるかどうか...。
#include <string>
#include <string_view>
std::string_view sub_string(std::string_view s,
std::size_t p,
std::size_t n = std::string_view::npos)
{
return s.substr(p, n);
}
std::string sub_string(std::string&& s,
std::size_t p,
std::size_t n = std::string::npos)
{
return s.substr(p, n);
}
std::string sub_string(std::string const& s,
std::size_t p,
std::size_t n = std::string::npos)
{
return s.substr(p, n);
}
int main()
{
using namespace std::literals;
auto source = "foobar"s;
auto bar = sub_string(std::string_view(source), 3);
// but uh-oh...
bar = sub_string("foobar"s, 3);
}
コンパイラはここで警告するようなことは何も見つけられませんでした。私はコードレビューもそうでないと確信しています。
私は以前にも言ったことがありますが、c++委員会の誰かが見ている場合に備えて、もう一度言います。
から暗黙のうちに変換することを許可することです。
std::string
から
std::string_view
は、c++の評判を落とすだけのひどいエラーです。
.
アップデート
この (私にとって) かなり心配な string_view のプロパティを cpporg メッセージボードに提起しましたが、私の懸念は無関心に扱われました。
このグループからのアドバイスのコンセンサスは、次のとおりです。
std::string_view
は決して関数から返してはいけないということです。つまり、上記の私の最初の提案は悪い形式だということです。
もちろん、(例えばテンプレート展開によって)これが偶然に起こる時をキャッチするためのコンパイラの助けはありません。
その結果
std::string_view
は、メモリ管理の観点からは、もはや存在しないかもしれない別のオブジェクトの状態を指すコピー可能なポインタと同等であるため、細心の注意を払って使用されるべきです。しかし、それは他のすべての点で、値型のように見え、動作します。
したがって、次のようなコードになります。
auto s = get_something().get_suffix();
安全なのは
get_suffix()
は
std::string
(を返します(値または参照による)。
を返すようにリファクタリングされた場合、UB となります。
std::string_view
.
つまり、私の考えでは、返された文字列を格納するユーザコードはすべて
auto
を返すようにリファクタリングされた場合、そのライブラリは壊れてしまいます。
std::string_view
の代わりに
std::string const&
.
ですからこれからは、少なくとも私にとっては、"almost always auto" は "almost always auto, except when it's strings" にならなければならないでしょう。
関連
-
[解決済み】ファイルから整数を読み込んで配列に格納する C++ 【クローズド
-
[解決済み】演算子のオーバーロード C++; <<操作のパラメータが多すぎる
-
[解決済み】警告 - 符号付き整数式と符号なし整数式の比較
-
[解決済み] std::string を const char* または char* に変換する方法
-
[解決済み] 文字列の単語を反復処理するにはどうすればよいですか?
-
[解決済み] std::stringのインスタンスを小文字に変換する方法
-
[解決済み] std::stringをintに変換するにはどうしたらいいですか?
-
[解決済み] sprintfのようなstd::stringの書式設定
-
[解決済み】char*をstd::stringに変換する。
-
[解決済み】std::string_viewはconst std::string& よりも具体的にどのように速いのでしょうか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】LLVMで暗黙のうちに削除されたコピーコンストラクタの呼び出し
-
[解決済み】非静的メンバ関数への参照を呼び出す必要がある
-
[解決済み】「corrupted size vs. prev_size」glibc エラーを理解する。
-
[解決済み】浮動小数点例外エラーが発生する: 8
-
[解決済み】fpermissiveフラグは何をするのですか?
-
[解決済み] 非静的データメンバの無効な使用
-
[解決済み] [Solved] インクルードファイルが開けません。'stdio.h' - Visual Studio Community 2017 - C++ Error
-
[解決済み】標準ライブラリにstd::endlに相当するタブはあるか?
-
[解決済み】C++ - ステートメントがオーバーロードされた関数のアドレスを解決できない。
-
[解決済み】演算子のオーバーロード C++; <<操作のパラメータが多すぎる