string s = "Hello world";
char* s2 = s.c_str();
S2 có được phân bổ trên ngăn xếp hoặc trong heap không? Nói cách khác ... Tôi có cần xóa s2 không?
s2
có trên ngăn xếp, có. Tuy nhiên, nó là một con trỏ đến một ký tự (trong trường hợp này xảy ra là ký tự đầu tiên trong một biểu diễn ASCIIZ của nội dung văn bản của s
). Bản thân văn bản đó là nơi đối tượng s
cảm thấy giống như việc xây dựng biểu diễn đó.Việc triển khai được phép thực hiện điều đó theo cách mà họ thích, nhưng lựa chọn thực hiện quan trọng đối với std::string
là liệu chúng có cung cấp "tối ưu hóa chuỗi ngắn" cho phép các chuỗi rất ngắn được nhúng trực tiếp trong đối tượng s
và liệu "Hello world" có đủ ngắn hay không được hưởng lợi từ tối ưu hóa mà:
- nếu như vậy, sau đó
s2
sẽ trỏ đến ngăn xếp bộ nhớ được phân bổ trong s
- khác, bên
s
sẽ có một con trỏ đến/đống phân bổ bộ nhớ lưu trữ giải phóng trong đó "Hello world \ 0 "nội dung có địa chỉ được trả về bởi .c_str()
sẽ xuất hiện và s2 sẽ là bản sao của giá trị đó.
Lưu ý rằng c_str()
là const
, vì vậy đối với mã của bạn để biên dịch bạn cần phải thay đổi để const char* s2 = ...
.
Bạn không cần xóa s2, không. Dữ liệu mà các điểm s2 vẫn thuộc sở hữu và được quản lý bởi đối tượng s
, sẽ bị vô hiệu hóa bởi bất kỳ lệnh gọi nào theo phương thức không const
của s
hoặc bằng s
không nằm ngoài phạm vi.
string s = new string("Hello, mr. heap...");
char* s2 = s.c_str();
sẽ S2 tại được trên heap, như nguồn gốc của nó là trên heap?
Mã này không biên dịch, vì s
không phải là con trỏ và chuỗi không có hàm tạo như string(std::string*)
. Bạn có thể thay đổi nó hoặc là:
string* s = new string("Hello, mr. heap...");
... hoặc ...
string s = *new string("Hello, mr. heap...");
Sau đó tạo ra một rò rỉ bộ nhớ và phục vụ không có mục đích hữu ích, vì vậy chúng ta hãy giả định trước đây. Sau đó:
char* s2 = s.c_str();
... cần phải trở thành ...
char* s2 = s->c_str();
sẽ S2 tại được trên heap, như nguồn gốc của nó là trên heap?
Có. Trong tất cả các tình huống, đặc biệt là nếu s
chính nó là trên heap, sau đó:
- thậm chí nếu có một chuỗi ngắn tối ưu hóa bộ đệm bên trong
s
mà c_str()
mang lại một con trỏ, nó phải nằm trên đống, nếu không
- nếu
s
sử dụng con trỏ để nhớ thêm để lưu trữ văn bản, bộ nhớ đó cũng sẽ được cấp phát từ heap.
Nhưng một lần nữa, ngay cả khi biết chắc chắn rằng s2
điểm để bộ nhớ heap phân bổ, mã của bạn không cần phải deallocate bộ nhớ đó - nó sẽ được thực hiện tự động khi s
bị xóa:
string* s = new string("Hello, mr. heap...");
const char* s2 = s->c_str();
...use s2 for something...
delete s; // "destruct" s and deallocate the heap used for it...
Trong số tất nhiên, tốt hơn hết là chỉ sử dụng string s("xyz");
trừ khi bạn cần một tuổi thọ vượt quá phạm vi địa phương và std::unique_ptr<std::string>
hoặc std::shared_ptr<std::string>
nếu không.
Thú vị, vì vậy, bạn sẽ không bao giờ giải phóng char * vì làm như vậy sẽ giải phóng dữ liệu nội bộ trong chuỗi? c_str() theo nghĩa đen giữ cùng địa chỉ với dữ liệu thực tế mà chuỗi đang sử dụng? Nhiều cuộc gọi đến .c_str() sẽ trả lại cùng một địa chỉ theo cách đó? (Chỉ cần làm rõ vì vậy tôi biết rằng tôi hiểu) –
@Georges câu trả lời cho một số câu hỏi đó phụ thuộc vào việc bạn đang sử dụng tiêu chuẩn mới nhất hay tiêu chuẩn cũ. Bạn có thể muốn làm rõ một trong những bạn đang quan tâm. –
@ R.MartinhoFernandes Tốt hơn đi với các tiêu chuẩn mới nhất. Sẽ là thú vị mặc dù để biết làm thế nào gần đây tiêu chuẩn này là –