2009-04-17 22 views
14

Trong std :: string chỉ có các thành viên const để lấy dữ liệu như c_str(). Tuy nhiên tôi có thể nhận được một tham chiếu đến phần tử đầu tiên của chuỗi thông qua operator[] và tôi có thể viết cho nó.Có hợp pháp để ghi vào std :: string không?

Ví dụ, nếu tôi có chức năng:

void toupper(char *first,char *last_plus_one); 

tôi có thể viết trực tiếp vào vector nhận được một con trỏ đến phần tử đầu tiên:

vector<char> message // has "Some Message"; 
toupper(&message[0],&message[0]+message.size()); 

Tôi có thể làm điều tương tự với std :: string ?

string message="Some Message"; 
toupper(&message[0],&message[0]+message.size()); 

Chuẩn có đảm bảo rằng vị trí của bộ nhớ thực sự tuyến tính không? tức là:

&(*(message.begin()+n)) == &message[n] 

Cảm ơn.

+0

Có thể bạn không chỉ đơn giản là templatize chức năng toupper cho phép sử dụng lặp chuỗi thay vì con trỏ? – jalf

+0

Nếu tôi không thể hỏi. Hãy nghĩ rằng tôi có một thư viện lớn thứ 3 có thể hỗ trợ unicode hoặc những thứ khác và api của họ hoạt động với con trỏ. Bởi vì nó chỉ là chi phí để thực hiện điều này như là mẫu. – Artyom

+0

@ jalf: Tôi không có tiêu chuẩn trong tầm tay, nhưng tôi tin rằng std :: to_upper là chính xác những gì bạn đề xuất. –

Trả lời

17

std :: chuỗi sẽ được yêu cầu để có bộ nhớ tiếp giáp với tiêu chuẩn C++ 0x mới. Hiện tại đó là hành vi không xác định.

+7

Có trình biên dịch đã biết sử dụng các chuỗi không tiếp giáp không? I E. Tôi có thể liên hệ trong 99% các trường hợp (có thể chỉ cần làm việc xung quanh cho các trình biên dịch cụ thể để tránh sao chép trên không) – Artyom

+6

Tôi luôn nghĩ rằng nó sẽ 'gọn gàng' để có một trình biên dịch/thư viện (quá) những thứ này. Nó sẽ làm những điều khó khăn/không hiệu quả/cách bất ngờ trong khi vẫn đang được tuân thủ. –

+0

@Dan: Tôi tin rằng Dinkumware và STLport đều có một STL gỡ lỗi bắt tất cả các loại vấn đề không tuân thủ của khách hàng (và sẽ phát ra các thông báo cảnh báo). Nhưng tôi có thể nhớ những điều sai trái. –

-1

Tôi nghĩ rằng nó cung cấp cho bạn một hành vi không xác định. Sử dụng một chuỗi để ghi vào, và sau đó sử dụng thành viên str() để lấy chuỗi của luồng.

+1

Sai. Bạn có thể viết vào một chuỗi. –

22

Herb Sutter có này để nói (http://herbsutter.wordpress.com/2008/04/07/cringe-not-vectors-are-guaranteed-to-be-contiguous/#comment-483): (! Nhưng không nhất thiết null-terminated)

hiện ISO C++ đòi hỏi & str [0] ho lên một con trỏ đến dữ liệu chuỗi liền kề, vì vậy không có nhiều thay đổi để những người triển khai có các chuỗi không liền nhau. Đối với C++ 0x, chúng tôi đã chấp nhận bảo đảm rằng std :: nội dung chuỗi phải thực sự được lưu trữ liên tục. Để biết chi tiết, hãy xem http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#530

Và Matt Austern nói tương tự trong tài liệu tham chiếu (http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#530). Vì vậy, có vẻ như bạn có thể giả định rằng một khi bạn gọi str [0] bạn sẽ nhận được một mảng có thể sửa đổi các ký tự (nhưng lưu ý rằng nó không bắt buộc phải là null chấm dứt).

+0

Trên thực tế từ các liên kết tôi thấy C++ 03 không yêu cầu bộ nhớ liên tục, nhưng trong thực tế không có triển khai khác. – Artyom

+0

Tôi biết tốt hơn là nghi ngờ Sutter, nhưng có ai có tham chiếu đến & str [0] được yêu cầu để mang lại một con trỏ đến dữ liệu liền kề? – jalf

+1

Theo Austern, việc truy cập thông qua toán tử [] yêu cầu mảng liền kề, truy cập thông qua một trình lặp không (vì vậy & str.begin() sẽ không). Tôi sẽ không tranh luận với héo héo hay Austern, nhưng tôi vẫn không đủ tự tin rằng tôi đặt "Vì vậy, có vẻ như" từ chồn trong. –

5

Có, bạn có thể sửa đổi một chuỗi.

Bạn cũng có thể sử dụng nó trong các thuật toán sử dụng trình lặp.

Bạn không thể sử dụng nó theo cách giống như một véc tơ <> vì không đảm bảo rằng các phần tử nằm trong các vị trí bộ nhớ liền kề (chưa: sắp đến một chuẩn gần bạn).

Vì vậy, nếu bạn sửa đổi cách tiếp cận của mình để sử dụng trình vòng lặp thay vì con trỏ, nó sẽ hoạt động. Và bởi vì các trình vòng lặp hành xử rất giống với các con trỏ nên những thay đổi mã nên không đáng kể.

template<typename I> 
void toupper(I first,I last_plus_one) 
{ 
    // Probably the same code as you had before. 
} 


{ 
    std::string s("A long string With Camel Case"); 

    toupper(s.begin(),s.end()); 
} 
3

Như đã được chỉ ra, người ta có thể sử dụng các chuỗi trong thuật toán sử dụng trình lặp; trường hợp tương tự có thể được thực hiện bằng std::transform Ex: - xem xét một chuỗi 's' để được chuyển đổi sang chữ thường:

int (*pf)(int)=tolower; //lowercase 
std::transform(s.begin(), s.end(), s.begin(), pf); 

Kính trọng,

Các vấn đề liên quan