2012-01-09 2 views
5

Tôi có đoạn mã sau:phạm vi và C++ con trỏ

using namespace std; 
vector<string*> v; 
{ 
    string s = "hello"; 
    v.push_back(&s); 
} 
{ 
    string ss = "goodbye"; 
    v.push_back(&ss); 
} 

cout << v.at(0)->c_str() << endl; 
cout << v.at(1)->c_str() << endl; 

mà in

goodbye 
goodbye 

nếu tôi loại bỏ các phạm vi dấu ngoặc đơn mã sẽ in

hello 
goodbye 

Chính xác những gì sẽ xảy ra khi Tôi rời khỏi phạm vi đầu tiên, mà con trỏ đến chuỗi đầu tiên bây giờ trỏ đến một thứ hai?

+1

UB, Luke! Đây chỉ là UB. Bạn đã may mắn rằng máy tính của bạn không phát nổ. –

+1

Tôi có thể giới thiệu cho bạn câu trả lời nổi tiếng hiện tại cho câu hỏi này: http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope – Benj

+0

Yup, [crossing các luồng] (http://en.wikipedia.org/wiki/Proton_pack#Crossing_the_Streams) một lần nữa. –

Trả lời

7

Con trỏ được lưu trữ trở thành con trỏ lơ lửng sau phạm vi và bất kỳ nỗ lực nào để đọc những gì chúng trỏ đến để mang lại hành vi không xác định.

+0

đó là những gì tôi nghĩ sẽ xảy ra, nhưng thực tế là kết quả là hằng số tôi phải hỏi. – Bg1987

+2

hành vi không xác định nghĩa là mọi thứ có thể xảy ra, bao gồm việc nhận được các kết quả tìm kiếm, nhất quán bình thường. Đây là một trong những lý do hành vi không xác định là xấu như vậy; bạn có thể thậm chí không nhận thấy nó khi bạn viết một chương trình, nhưng chương trình của bạn có thể thất bại thảm khốc trong một số trường hợp khác. – bames53

+0

@ Bg1987: Hành vi không xác định không có nghĩa là hành vi ngẫu nhiên. Sự ngẫu nhiên thực sự không tồn tại :) Nó có nghĩa là những gì sẽ xảy ra không bị ràng buộc bởi bất kỳ quy tắc nào (từ quan điểm chuẩn), nhưng đầu ra của trình biên dịch vẫn bị ràng buộc bởi các quy tắc sản xuất mã của trình biên dịch, vì vậy phạm vi các hành vi mà nó có thể cung cấp bị hạn chế. –

3

Điều gì xảy ra có hành vi không xác định, vì s nằm ngoài phạm vi tại thời điểm bạn tham chiếu trong cuộc gọi tới nhà điều hành cout<<.

Nó không sụp đổ vì sssxảy ra để có cùng địa chỉ với kiến ​​trúc cụ thể của bạn và việc triển khai C++. Nói cách khác, những người khác cố gắng sao chép thử nghiệm của bạn trên các kiến ​​trúc khác hoặc với các trình biên dịch khác có thể sẽ nhận được các kết quả khác nhau.

2

Bạn đang dereferencing hai con trỏ tới hai đối tượng đã bị hủy: đây là hành vi không xác định. Mọi thứ đều có thể xảy ra ở đây.

+0

có con trỏ trỏ đến một số vị trí không hợp lệ không phải là hành vi không xác định; bỏ qua chúng là –

+0

@phresnel, vâng. Đã chỉnh sửa. – hmjd

3

Trong thực tế, hệ thống đang sử dụng lại bộ nhớ được sử dụng cho chuỗi s để giữ chuỗi ss. Nhưng điều này chỉ xảy ra là trình biên dịch đang quản lý bộ nhớ như thế nào; theo tiêu chuẩn C++ bạn không thể dựa vào bất kỳ hành vi nào như vậy và kết quả thực tế của mã bạn đã đăng là không xác định.