62

SO ドキュメントの文字列のトピックでは、備考セクションで次のように述べていました。

C++14 以降、 を使用する代わりに、文字列リテラルと同様に、 を に変換するを"foo"使用することをお勧めします。"foo"ssconst char * "foo"std::string "foo"

私が使用して見る唯一の利点

std::string str = "foo"s;

それ以外の

std::string str = "foo";

最初のケースでは、コンパイラはコピー省略を実行できます (私が思うに)。これは、2 番目のケースでのコンストラクター呼び出しよりも高速です。

それにもかかわらず、これは (まだ) 保証されていないため、最初のものはコンストラクター (コピー コンストラクター) も呼び出す可能性があります。

次のようなリテラルを使用する必要がある場合を無視するstd::string

std::string str = "Hello "s + "World!"s;

std::stringリテラルの代わりにリテラルを使用する利点はありconst char[]ますか?

4

4 に答える 4

54

あなたが「Almost Always Auto」グループの一員である場合、UDL は非常に重要です。これを行うことができます:

auto str = "Foo"s;

したがって、はではなく、str本物のになります。したがって、いつ何をするかを決めることができます。std::stringconst char*

これは、戻り型の自動推論にも重要です。

[]() {return "Foo"s;}

または、実際には型推論の任意の形式:

template<typename T>
void foo(T &&t) {...}

foo("Foo"s);

[...] の代わりに [...] を使用する唯一の利点は、最初のケースでコンパイラーがコピー省略を実行できることです (私が思うに)。これは、2 番目のケースでのコンストラクター呼び出しよりも高速です。

コピー省略は、コンストラクター呼び出しよりも高速ではありません。いずれにせよ、オブジェクトのコンストラクターの 1 つを呼び出しています。問題はどちらかです:

std::string str = "foo";

これにより、コンストラクターへの呼び出しがstd::string発生しますconst char*。ただしstd::string、文字列を独自のストレージにコピーする必要があるため、文字列の長さを取得する必要があります。そして、長さがわからないため、このコンストラクターは長さstrlenを取得するために使用する必要があります (技術的にはchar_traits<char>::length、しかし、おそらくそれほど速くはなりません)。

対照的に:

std::string str = "foo"s;

これは、次のプロトタイプを持つ UDL テンプレートを使用します。

string operator "" s(const char* str, size_t len);

ほら、コンパイラは文字列リテラルの長さを知っています。そのため、UDL コードには文字列へのポインタとサイズが渡されます。したがって、 aおよびastd::stringを取るコンストラクターを呼び出すことができます。したがって、文字列の長さを計算する必要はありません。const char* size_t

問題のアドバイスは、リテラルのすべてsの使用をバージョンに変換することではありません。s の配列の制限に問題がなければchar、それを使用してください。アドバイスは、そのリテラルを a に保存する場合はstd::string、それがまだリテラルであり、漠然としたものではない間にそれを行うのが最善であるということconst char*です。

于 2016-07-28T03:09:08.630 に答える
22

使用するアドバイス"blah"sは、効率とは関係なく、すべて初心者コードの正確性と関係があります。

C のバックグラウンドを持たない C++ の初心者は、その"blah"結果が適切な文字列型のオブジェクトになると想定する傾向があります。たとえば"blah" + 42、多くのスクリプト言語で動作する のようなものを書くことができるようにします。ただし、C++では"blah" + 42、未定義の動作が発生し、文字配列の末尾を超えてアドレス指定されます。

しかし、その文字列リテラルが次のように記述されている場合、"blah"s代わりにコンパイル エラーが発生します。これははるかに望ましいことです。

于 2016-07-28T03:22:25.660 に答える
16

さらに、UDL を使用すると\0、文字列に簡単に含めることができます。

std::string s = "foo\0bar"s; // s contains a \0 in its middle.
std::string s2 = "foo\0bar"; // equivalent to "foo"s
于 2016-07-28T08:31:00.637 に答える
2
  1. strlenC++ 文字列リテラルを使用するということは、長さを計算するために呼び出す必要がないことを意味します。コンパイラはすでにそれを認識しています。
  2. 文字列データがグローバル空間のメモリを指しているライブラリの実装を許可する可能性があります。C リテラルを使用すると、構築時にデータのコピーをヒープ メモリに常に強制する必要があります。
于 2016-07-28T03:13:19.480 に答える