2016-02-11 10 views
5
int main(int argc, char const *argv[]) 
{ 
    const char *s1 = "hello"; 
    string s2; 
    s2 = s1; 
    s2.reserve(10); 
    s2[5] = '.'; 
    s2[6] = 'o'; 
    s2[7] = '\0'; 
    cout << "[" << s1 << "] [" << s2 << "]" << endl; 
    return 0; 
} 

上記のコードでは、s2が正しく出力されません。 hello.oの代わりに、常にhelloを印刷します。 s2のサイズは、最初の割り当て後も常に5のままです。なぜこれはそうですか?割り当て後にC++の文字列サイズが更新されない

答えて

4

s2.reserve()の代わりにs2.resize()を使用する必要があります。

10

operator[]文字列のサイズを変更しません。また、インデックス5,6,7の呼び出しは範囲外であり、定義されていない動作です。 resizeを使用して文字列を特定のサイズに設定するか、文字を追加する場合はpush_backまたはoperator+=を使用します。

std::stringを手動でゼロにする必要はありません。クラスはそれを単独で処理します。あなたが本当にそれらを望むなら、あなたはそこにゼロを埋め込むことが許されていますが、それは文字列の長さの一部とみなされます。

+0

ですか?私は、プログラムが実行時にエラーになると思います。 – DDoSolitary

+0

@Stalkerそうかもしれないし、そうでないかもしれない。 –

+1

@Stalker:はい、未定義の動作です。範囲外のアクセス(例外)を定義したい場合は、 'at'を使用してください。 –

6

s2.reserve(10);文字列がまったく伸びない場合は、コンテナに少なくとも10文字のreserve enough memoryと通知されます。予約されたスペースには何も記入しません。

したがって、それをs2[5]にインデックス付けすると、基本的に "使用された"文字列(つまりそのサイズ)の境界の外側にインデックスが付けられますが、これは未定義の動作です。

サイズを変更するには、s2.resize(10);を使用できます。これにより、文字列が適切に割り当てられて埋められ、サイズは10になります。同時に文字を割り当てて挿入するには、push_back()またはoperator+=を使用することもできます。

注:s2[7] = '\0';は不要です。 stringクラスは、c_str()などのメソッドに必要なNUL終端を内部的に管理します.NULを自分で追加する必要はありません。

2

std::string::reserveはメモリを割り当てますが、文字列のサイズは変更しません。あなたの例では:

s2 = s1;   // Resize string to 6 characters 
s2.reserve(10); // Allocate another 4 char, but not resize 
s2[5] = '.';  // Write '.' to some memory, but the string is still not resized. 

簡単に修正がstd::string::resizeの代わりreserve使用することです。

0

短い答え:使用リサイズ(10)の代わりに、予備(10)

長い答え:のstd ::文字列の実装で は、二つの変数のサイズと容量があります。 容量は、文字列に割り当てられたメモリの量です。 サイズは、あなたの文字列にいくつの有効な要素(あなたの場合はchar)が許されているかです。 容量は常にサイズ以下であることに注意してください。 reserve()を呼び出すと、容量が変更されます。

if (size > capacity){ 
capacity = max(size, capacity*2); //Why multiply capacity by 2 here? This is to achieve amortized O(1) while resizing 
} 

をここでOPが望んでいるのコード例を示します。この式は、その後適用されることになるで通話リサイズ()、あなたのサイズを変更する可能性があるだけでなく、サイズ>容量ならば、あなたも容量を変更します 、サイズや容量のより良い説明のためにいくつかのより多くのコード

#include <iostream> 
#include <string.h> 
using namespace std; 

int main(int argc, char const *argv[]) 
{ const char *s1 = "hello"; 
    string s2; 
    s2 = s1; 
    cout << "length of s2 before reserve: " << s2.length() << endl; 
    cout << "capacity of s2 before reserve: " << s2.capacity() << endl; 
    s2.reserve(10); 
    cout << "length of s2 after reserve: " << s2.length() << endl; //see how length of s2 didn't change? 
    cout << "capacity of s2 after reserve: " << s2.capacity() << endl; 
    s2.resize(8); //resize(10) works too, but it seems like OP you only need enough size for 8 elements 
    cout << "length of s2 after resize: " << s2.length() << endl; //size changed 
    cout << "capacity of s2 after resize: " << s2.capacity() << endl; //capacity didn't change because size <= capacity 
    s2[5] = '.'; 
    s2[6] = 'o'; 
    s2[7] = '\0'; 
    cout << "[" << s1 << "] [" << s2 << "]" << endl; 
    // You're done 

    // The code below is for showing you how size and capacity works. 
    s2.append("hii"); // calls s2.resize(11), s[8] = 'h', s[9] = 'i', s[10] = 'i', size = 8 + 3 = 11 
    cout << "length of s2 after appending: " << s2.length() << endl; // size = 11 
    cout << "capacity of s2 after appending: " << s2.capacity() << endl; //since size > capacity, but <= 2*capacity, capacity = 2*capacity 
    cout << "After appending: [" << s1 << "] [" << s2 << "]" << endl; 
    return 0; 

結果:それは未定義

length of s2 before reserve: 5 
capacity of s2 before reserve: 5 
length of s2 after reserve: 5 
capacity of s2 after reserve: 10 
length of s2 after resize: 8 
capacity of s2 after resize: 10 
[hello] [hello.o] 
length of s2 after appending: 11 
capacity of s2 after appending: 20 
After appending: [hello] [hello.ohii] 
関連する問題