2016-02-11 15 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; 
} 

Mã trên không in chính xác s2. Thay vì hello.o, nó luôn luôn in hello. Có vẻ như kích thước của s2 vẫn ở mức 5 luôn sau lần gán đầu tiên. Tại sao cái này rất?Kích thước chuỗi C++ không được cập nhật sau khi gán

Trả lời

4

Bạn nên sử dụng s2.resize() thay vì s2.reserve().

10

operator[] không thay đổi kích thước chuỗi. Và các cuộc gọi của bạn với chỉ số 5, 6 và 7 nằm ngoài phạm vi và hành vi không xác định. Sử dụng resize để đặt chuỗi thành kích thước cụ thể hoặc push_back hoặc operator+= để nối thêm các ký tự.

Cũng lưu ý rằng bạn không cần phải chấm dứt std::string theo cách thủ công. Lớp học sẽ tự mình xử lý. Mặc dù bạn được phép có các số 0 được nhúng trong đó nếu bạn thực sự muốn chúng, và chúng sẽ được coi là một phần của chiều dài của chuỗi.

+0

có không xác định? Tôi nghĩ chương trình sẽ gặp lỗi khi chạy. – DDoSolitary

+0

@Stalker Có thể có hoặc không. –

+1

@Stalker: Có, đó là hành vi không xác định. Nếu bạn muốn xác định ngoài giới hạn truy cập (một ngoại lệ), sử dụng 'at'. –

6

s2.reserve(10); không phát triển chuỗi nào cả, nó chỉ báo cho vùng chứa là reserve enough memory cho ít nhất 10 ký tự. Nó không lấp đầy không gian dành riêng với bất cứ thứ gì.

Do đó, khi bạn lập chỉ mục nó s2[5] bạn về cơ bản chỉ mục bên ngoài giới hạn của chuỗi "đã sử dụng" (nghĩa là kích thước của nó), đó là hành vi không xác định.

Để đổi kích thước, bạn có thể sử dụng s2.resize(10);. Điều này sẽ phân bổ và điền vào chuỗi một cách thích hợp và nó sẽ có kích thước là 10. Để phân bổ và chèn một ký tự cùng một lúc, bạn cũng có thể sử dụng push_back() hoặc operator+=.

Trên ghi chú bên: s2[7] = '\0'; là không cần thiết. Lớp string quản lý nội bộ bất kỳ kết thúc NUL nào cần thiết cho các phương thức như c_str() v.v. Bạn không cần phải tự thêm NUL.

2

std::string::reserve chỉ cấp phát bộ nhớ, nhưng không thay đổi kích thước chuỗi. Trong ví dụ của bạn:

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. 

Sửa chữa dễ dàng là sử dụng std::string::resize thay vì reserve.

0

Câu trả lời ngắn: sử dụng thay đổi kích thước (10) thay vì dự trữ (10)

Long trả lời: Trong việc thực hiện std :: string, có kích thước và công suất hai biến. Dung lượng là dung lượng bộ nhớ bạn đã cấp cho chuỗi. Kích thước là số lượng phần tử hợp lệ (trong trường hợp của bạn, char), được cho phép trong chuỗi của bạn. Lưu ý rằng dung lượng sẽ luôn nhỏ hơn hoặc bằng với kích thước. Khi bạn gọi dự trữ(), bạn đang thay đổi dung lượng. Khi thay đổi kích thước() cuộc gọi của bạn, bạn có thể không chỉ được thay đổi kích thước, nhưng bạn cũng sẽ thay đổi công suất nếu size> công suất, trong đó công thức này sau đó sẽ được áp dụng:

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

Dưới đây là một ví dụ mã của những gì OP muốn và một số mã hơn cho một lời giải thích tốt hơn về kích thước và công suất

#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; 

Kết quả:

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] 
Các vấn đề liên quan