2016-01-20 32 views
21

私はポインタと長さを返す関数を持っており、std::string::assign(pointer, length)に電話したいと思います。長さがゼロでポインタがnullptrの場合、特別なケース(clear)を作らなければならないのですか?nullptrをstd :: string :: assignに渡すことは有効ですか?

C++標準は言う:

21.4.6.3 basic_string::assign 

basic_string& assign(const charT* s, size_type n); 
Requires: s points to an array of at least n elements of charT. 

だから何n場合はゼロになりますか?ゼロ文字の配列とは何ですか?また、ゼロ文字をどのように指していますか? それは

s.assign(nullptr, 0); 

を呼び出すために有効になっていたり、それは未定義の動作ですか?

サイズnが0の場合、libstdC++の実装はポインタsを逆参照しないように見えますが、それはほとんど保証されません。

+0

関連するノートでは、 'char a [4]; s.assign(s + 4、0); '合法ですか?これは「長さ0の配列」の合理的な解釈のようであり、実際にはおそらく起こりうる。 –

答えて

19

Peduchically、nullptrは、サイズ>=0の配列を指す要件を満たしていないため、標準では動作が保証されていません(UBです)。

一方、nがゼロの場合、ポインターがサイズゼロの配列になる可能性があり、そのようなポインターを逆参照すると、定義されていない動作が発生するため、実装はポインターを逆参照できません。また、何もコピーされていないので、そうする必要はありません。

上記の推論は、UBを無視しても問題ないことを意味するものではありません。しかし、s.assign(nullptr, 0)を禁止する理由がない場合は、標準の表現を「nがゼロより大きく、sが〜を指す場合」に変更することが望ましい場合があります。それを拒否する正当な理由はわかりませんが、正当な理由が存在しないと約束することはできません。チェックを追加することがほとんど複雑であることを

注:new char[0]

s.assign(ptr ? ptr : "", n); 

これがゼロの文字

の配列は何ですか。自動または静的記憶域の配列のサイズがゼロでない可能性があります。標準(2.14.7)[lex.nullptr]から

+6

実装では、ポインタの有効性を確認することができます。ポインタが割り当てられたメモリを指しているかどうかをチェックするか、あるいは__debug_assert(cstr!= nullptr)という簡単なチェックが存在するかどうかを確認してください。 –

+0

@Revolver_Ocelotこれは標準では動作を保証するものではありません。私は、ポインターが逆参照される場合にのみ、ポインタをチェックする実装を期待しています。 – user2079303

+0

長さをゼロにする特別なケースを作る必要がある場合、私は 'clear()'を呼び出す方が好きです。 – Bulletmagnet

12

あなたが指摘しているように、標準では「sが配列を指しています...」と表示されています。ヌルポインタは、任意の数の要素の配列を指しません。 0要素さえありません。また、sは "少なくともn要素の配列..."を指していることに注意してください。したがって、nが0の場合でも、正当なポインタを配列に渡すことは可能です。

全体としてstd::stringのAPIは、charTへのヌルポインタに対して十分に保護されていません。だからあなたはそれに渡すポインタがnullでないことを常に確認するべきです。

9

なぜ実装が長さがゼロとして提供されている配列へのポインタを逆参照するのかわかりません。

しかし、私は注意の面で間違っていると言いました。

21.4.6.3のbasic_string ::

を割り当てる必要です:あなたは規格の要件を満たしていないと主張している可能性のポイントをチャート

の少なくともn個の要素の配列に

アレイを指していないためです。

技術的には、動作は未定義です。

5

ポインタリテラルは、キーワードnullptrあります。これはタイプstd::nullptr_tの値です。 【注:std::nullptr_t はポインタ型でもメンバー型へのポインタでもない特殊タイプは...です]

std::nullptr_t暗黙4.10.1に従ってヌルポインタの任意のタイプに変換することができます[ conv.ptr]。ヌルポインタのタイプにかかわらず、実際にはには何もありませんを指しています。

したがって、は、charTのn個以上の要素の配列を指しています。

これは未定義の動作です。興味深いことに、this answerによれば、C++ 11標準では、sbasic_stringコンストラクタ内のヌルポインタであってはならないことが明確に述べられていますが、この文言は削除されています。

+2

真ですが、nullptr_tはchar *を含む任意の型のヌルポインタに暗黙的に変換できます。問題は、結果のヌルポインタが0文字ではなく、何も指していないことですが、型は問題ではありません。 – rici

+0

@riciありがとう。投稿を編集しましたが、他の提供された回答と非常に似ていることを恐れています。 – erip

関連する問題