2013-07-01 87 views
11

Tôi muốn truy cập địa chỉ bắt đầu của mảng được duy trì bởi lớp chuỗi.Phương thức c_str() nào từ lớp trả về chuỗi?

string str="hey"; 
char* pointer=(char*)str.c_str(); 
  1. là con trỏ trỏ đến địa chỉ của mảng (duy trì bởi lớp string)? hoặc chuỗi lớp sẽ tạo ra một mảng mới từ bộ nhớ động và sao chép chuỗi hiện có vào nó và trả về địa chỉ của nó?

  2. Nếu đây không phải là cách phù hợp, thì làm thế nào để truy cập địa chỉ bắt đầu của mảng được duy trì bởi lớp chuỗi?

+9

* Tại sao * bạn có muốn địa chỉ này không? Bạn đang cố gắng làm gì với chuỗi? – trojanfoe

+1

Bạn đang tìm kiếm câu trả lời C++ 11 hoặc C++ 03? Câu trả lời đúng tùy thuộc vào điều này. Nếu không có đặc tả kỹ hơn, tôi sẽ tiếp tục giả sử C++ 11. –

+0

Có thể bạn có thể trả lời các câu hỏi để chúng tôi có thể trả lời câu hỏi của bạn tốt hơn? Bạn đã ở đây vài phút trước. –

Trả lời

23

Trong C++ 11 chuẩn nó quy định rõ ràng rằng .c_str() (cũng như mới .data()) phải trả lại con trỏ đến bộ đệm bên trong được sử dụng bởi std::string.

Bất kỳ sửa đổi của std :: string sau khi có con trỏ qua .c_str()thể kết quả trong nói char * trở lại trở thành không hợp lệ (có nghĩa là - nếu std::string nội bộ đã phải tái phân bổ không gian).

Trong việc thực hiện các tiêu chuẩn C++ trước đó được phép trả lại bất kỳ thứ gì. Nhưng như là tiêu chuẩn không yêu cầu người sử dụng để deallocate kết quả, tôi đã không bao giờ nhìn thấy bất kỳ thực hiện trả lại bất cứ điều gì mới được phân bổ. Ít nhất GNU gcc và chuỗi STL của MSVC++ là mảng char được kết thúc bằng 0, được trả về bởi c_str().

Vì vậy, nó an toàn để giả định (với bình thường cho C++ thận trọng) rằng trong bất kỳ phiên bản của C++ trong bất kỳ nó thực hiện .c_str() sẽ trả về bộ đệm bên trong.

Nói cách khác - bạn sẽ không bao giờ giữ giá trị .c_str() trừ khi bạn chắc chắn 100% nó sẽ không thay đổi kích thước của nó bất kỳ lúc nào trong tương lai (trừ khi đó là const).

P.S. BTW, bạn không bao giờ nên làm char* pointer=(char*)str.c_str();. Đó là const char * và bạn không được sửa đổi nội dung, một phần vì ở trên - bạn có thể ghi đè lên bộ nhớ của một số đối tượng khác hoặc làm hỏng trạng thái nội bộ của std::string, trong trường hợp triển khai thực hiện điều gì đó lạ mắt, như lập chỉ mục các ký tự cho nhanh hơn .find() nhìn thấy điều đó, nhưng này - đó là một đóng gói!)

+0

Đây chính xác là câu trả lời tôi mong đợi. –

+0

... và tất nhiên sửa đổi một chuỗi * liên tục * sẽ gần như chắc chắn có hoàn cảnh nghiêm trọng do nơi nó sống trong quá trình (tức là có thể trên một trang bộ nhớ chỉ đọc). – trojanfoe

+1

@Andrian Nord Và nếu có 0 xác suất thay đổi kích thước thì ?? Tôi đã tạo một đối tượng chuỗi mới và sử dụng phương thức thay đổi kích thước (512). 512 là độ dài chuỗi tối đa có thể có trong ứng dụng của tôi. Bây giờ nếu tôi sử dụng c_str() để lấy địa chỉ và sau đó sử dụng phương thức append() trên đối tượng, nó sẽ ổn chứ? –

1

Bạn có thể lấy địa chỉ bắt đầu chuỗi bằng char *address = &str[0];. Không cần phải chuyển đổi chuỗi thành chuỗi ký tự đại diện.

+2

'const char', chắc chắn? –

+0

Tôi không nghĩ rằng đó là đảm bảo để hoạt động chính xác. – davmac

+0

@PeterWood Không, không bắt buộc. –

0

Trong C++ 11, con trỏ trả về điểm cho mảng nội bộ hiện đang được đối tượng chuỗi sử dụng để lưu trữ các ký tự phù hợp với giá trị của nó.

Tham khảo http://www.cplusplus.com/reference/string/string/c_str/ để biết thêm chi tiết.

+0

@trojanfoe liên kết tôi đăng trong câu trả lời cho biết: "Cả chuỗi :: dữ liệu và chuỗi :: c_str là từ đồng nghĩa và trả lại cùng một giá trị.", Bạn có ý là sai? –

+0

@trojanfoe Mọi thứ có thể khác trong C++ 11. Ít nhất http://stackoverflow.com/a/7554172/533480 đã nói như vậy. –

+0

Đồng ý; xóa các commnet của tôi. – trojanfoe

4

LƯU Ý: Câu trả lời của tôi chỉ đúng cho pre-C++11. Đối với C++ 11, this là câu trả lời đúng.


  1. Nó trả về một C-string với null-chấm dứt. std::string chính nó không phải là null chấm dứt, do đó, thực hiện được phép (và có lẽ sẽ) trả về một mảng mới được phân bổ là const char. Nếu việc tạo std::string không nằm ngoài phạm vi hoặc nếu bị đột biến, thì chuỗi c_str() bị hủy sẽ bị vô hiệu.

  2. data() trả về dữ liệu, nhưng hãy cẩn thận, nó không phải là chuỗi bị hủy.

Trong không trường hợp, bạn có nghĩa vụ phải tinh chỉnh dữ liệu đó, cả hai data()c_str() con trỏ trở lại const char, và bạn thực sự không nên.

Ví dụ: std::string s được phép là chuỗi được tính tham chiếu (mặc dù điều này không còn phổ biến nữa) hoặc thậm chí có thể sử dụng sơ đồ lập chỉ mục sôi nổi trên dữ liệu của chúng (chưa bao giờ thấy điều đó).

1

Nếu bạn thực sự muốn "dữ liệu" bên trong chuỗi, thì string::data() là hàm bạn đang tìm kiếm.

Lưu ý tuy nhiên, giống như c_str(), đó là con trỏ const đến dữ liệu - bạn không được phép sửa đổi dữ liệu này.

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