getString()
sẽ trả về bản sao str
(getString()
trả về theo giá trị);
Đúng vậy.
do đó, bản sao của str
sẽ giữ nguyên "còn sống" trong main()
cho đến khi trả lại main()
.
Không, sao lại là tạm thời std::string
, mà sẽ bị phá hủy vào cuối báo cáo kết quả, trong đó nó được tạo ra, ví dụ: trước std::cout << cStr << std::endl;
. Sau đó, cStr
trở nên lơ lửng, dereference trên nó dẫn đến UB, bất cứ điều gì là có thể.
Bạn có thể sao chép tạm thời trở lại biến được đặt tên hoặc liên kết nó với tham chiếu giá trị tham chiếu hoặc tham chiếu giá trị tham chiếu const
(thời gian tạm thời sẽ được kéo dài cho đến khi tham chiếu nằm ngoài phạm vi). Chẳng hạn như:
std::string s1 = getString(); // s1 will be copy initialized from the temporary
const char* cStr1 = s1.c_str();
std::cout << cStr1 << std::endl; // safe
const std::string& s2 = getString(); // lifetime of temporary will be extended when bound to a const lvalue-reference
const char* cStr2 = s2.c_str();
std::cout << cStr2 << std::endl; // safe
std::string&& s3 = getString(); // similar with above
const char* cStr3 = s3.c_str();
std::cout << cStr3 << std::endl; // safe
Dưới đây là một lời giải thích từ 10.4.10 Đối tượng tạm thời [class.temp]] [The.C++ Programming.Language.Special.Edition.]:
Trừ khi ràng buộc với một tham chiếu hoặc được sử dụng để khởi tạo một đối tượng được đặt tên, một đối tượng tạm thời bị hủy ở cuối biểu thức đầy đủ trong mà nó đã được tạo. Biểu thức đầy đủ là biểu thức là không phải là biểu thức phụ của một số biểu thức khác.
Lớp chuỗi chuẩn có hàm thành viên c_str() trả về một mảng ký tự kiểu C, không bị chấm dứt (§3.5.1, §20.4.1). Ngoài ra, toán tử + được định nghĩa có nghĩa là nối chuỗi. Đây là những cơ sở rất hữu ích cho chuỗi. Tuy nhiên, kết hợp chúng có thể gây ra các vấn đề tối nghĩa. Ví dụ:
void f(string& s1, string& s2, string& s3)
{
const char* cs = (s1 + s2).c_str();
cout << cs ;
if (strlen(cs=(s2+s3).c_str())<8 && cs[0]==´a´) {
// cs used here
}
}
Có thể phản ứng đầu tiên của bạn là "nhưng không làm điều đó" và tôi đồng ý. Tuy nhiên, mã như vậy không được viết, do đó, nó là giá trị biết làm thế nào nó là giải thích.
Đối tượng tạm thời của chuỗi lớp được tạo để giữ s1 + s2. Tiếp theo, một con trỏ tới một chuỗi kiểu C được trích xuất từ đối tượng đó. Sau đó - ở cuối biểu thức - đối tượng tạm thời bị xóa. Bây giờ, chuỗi phân cách kiểu C được phân bổ ở đâu? Có lẽ là một phần của đối tượng tạm thời giữ s1 + s2 và lưu trữ đó không được bảo đảm để tồn tại sau khi tạm thời bị hủy. Do đó, cs điểm để lưu trữ được phân phối lại. Các hoạt động đầu ra cout < < cs có thể hoạt động như mong đợi, nhưng đó sẽ là may mắn tuyệt đối. Trình biên dịch có thể phát hiện và cảnh báo chống lại nhiều biến thể của vấn đề này.
Mã của bạn hoạt động tốt đối với tôi. –
@PriyanshGoel Hành vi không xác định đôi khi giống như vậy. –
Tôi không thể hiểu lý do hành vi không xác định. –