std :: vector <char>からstd :: stringを構築する方法は?


115

最初にCスタイルの文字列を構築してから(それを使用して)std :: stringを作成するのではなく、文字のベクトルから文字列を初期化するためのより速い/代替/「より良い」方法はありますか?


4
これはコピーせずに実行できますか?つまり、新しいオブジェクトとしてstd::vector<char> v2(std::move(v))a と同じことを行うものstd::stringです。
tobi_s 2018年

回答:


197

まあ、最善の方法は次のコンストラクタを使用することです:

template<class InputIterator> string (InputIterator begin, InputIterator end);

これは次のようなものにつながります:

std::vector<char> v;
std::string str(v.begin(), v.end());

41

できると思う

std::string s( MyVector.begin(), MyVector.end() );

ここで、MyVectorはstd :: vectorです。


1
設定しない限り、実行時に無効なイテレータについてアサートするVS2013を除きます_ITERATOR_DEBUG_LEVEL=1(その場合、正常に動作すると思われます)。
キャメロン

35

C ++ 11を使用するstd::string(v.data())か、ベクトル'\0'の最後にaが含まれていない場合は、を使用できますstd::string(v.data(), v.size())


C ++ 98でも、std :: string(&v [0])を実行できると思います。もちろん、これはベクトルがnullで終了する場合です。
ジェイミー

1
@Jamie:ところで、C ++ 98に、string(&v[0], v.size())また動作しますが、後にのみ必要がありassert(not v.empty());、ベクトルが空の場合以来、両方v[0]v.front()未定義の動作を呼び出します。これは、address-of演算子を使用する必要がないという構文上の単純さを除けばdata()、空のベクトルでも機能するC ++ 11の関数の真の利点です。
Adam H. Peterson

とても本当です。残念ながら、私のプロジェクトは近い将来Visual Studio 2008に行き詰まっています。最初にベクターの長さをチェックすることについてです。
ジェイミー

ベクトルに '\ 0'が含まれていない場合はstd::string(v.data())、長い文字列になる可能性があります。したがって、この方法は使用しないでください。
heLomaN

@heLomaN:std::string(v.data(), v.size())その正確な理由で回答で明示的に言及されていたの何が問題になっていますか?
Sz。

12
std::string s(v.begin(), v.end());

ここで、vはほとんど反復可能です。(具体的には、begin()およびend()はInputIteratorsを返す必要があります。)


3

完全std::string(&v[0])を期すために、もう1つの方法があります(ただし、文字列がnullで終了していることを確認する必要があり、std::string(v.data())一般的に推奨されます。

違いは、前者の手法を使用して、バッファーを変更する関数にベクターを渡すことができることです。これは、.data()では行えません。


なぜdata()バッファの変更に使用できないのですか?data()非constベクトルを呼び出すとaが返されるように見えT *ます(そして、ベクトルがconstの場合、T const &とにかく'v [0] `が返されます)。
Adam H. Peterson

@ AdamH.Petersonそれは標準の見落としのようです。Std :: vectorのデータにはconst関数とnon-const関数の両方がありますが、現在の標準では、std :: stringにはconst関数しかありません:en.cppreference.com/w/cpp/string/basic_string/data C ++ 17は非constバージョンを追加しているため、これはいつまでも当てはまるわけではありませんが、現在の標準では「データを介してアクセスされる文字配列の変更には未定義の動作があります」と記載されています。
Riot

v文字列の場合も同様ですが、ターゲットタイプは文字列でvあり、ベクトルです。(しかし、C ++ 17が文字列をベクトルと同等にすることは素晴らしいことです。)
Adam H. Peterson

@ AdamH.Petersonもちろんそうです。質問は少し前に回答されましたが、質問全体がチェックなしの文字列に関するものだと思いました。
Riot

2

私はステファンの答えが好きです(Sep 11 '13)が、少し強くしたいと思います。

ベクトルがnullターミネーターで終わる場合は、(v.begin()、v.end())を使用しないでください。v.data()(またはC ++ 17より前のバージョンの場合は&v [0])を使用してください。 。

vにnullターミネーターがない場合は、(v.begin()、v.end())を使用する必要があります。

begin()とend()を使用し、ベクトルに終了ゼロがある場合、たとえば、文字列「abc \ 0」で終わることになります。たとえば、長さが4ですが、実際には「abc」のみでなければなりません。


1
vector<char> vec;
//fill the vector;
std::string s(vec.begin(), vec.end());

コードだけでなく、説明も追加できますか?
ポールフロイド

1
C ++ 11文字列ライブラリテンプレートは、次のようになります。デフォルト(1)string(); コピー(2)文字列(const string&str); substring(3)文字列(const string&str、size_t pos、size_t len = npos); c-stringから(4)string(const char * s); バッファから(5)文字列(const char * s、size_t n); fill(6)string(size_t n、char c); range(7)テンプレート<class InputIterator>文字列(最初にInputIterator、最後にInputIterator); 初期化子リスト(8)文字列(initializer_list <char> il); move(9)string(string && str)noexcept; 7番目のテンプレートに従っています。
TechCat

こんにちは@TechCat!次の質問に答える前に、良い答え書いて読んでください。SOでの滞在をお楽しみください!
ディギー。

説明を使用して回答を編集していただけませんか?
ポールフロイド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.