Thứ nhất: defer
được thực thi vì bạn có thể thấy rõ khi thêm print(str)
vào đó.
Bây giờ để giải thích tại sao giá trị trả về không phản ánh giá trị thay đổi:
Lý do cho điều này là String
là bất biến - bất cứ khi nào bạn viết str += something
bạn tạo một String
dụ hoàn toàn mới và lưu trữ nó bên trong str
.
Nếu bạn viết return str
trả về phiên bản hiện tại là str
là 123yyy4
. Sau đó, số defer
được gọi và chỉ định String
123yyy4xxx
đến str
hoàn toàn mới và không liên quan. Nhưng điều đó không thay đổi đối tượng String
trước đó được lưu trữ bên trong str
, nó chỉ ghi đè lên nó và do đó không ảnh hưởng đến return
đã "xảy ra".
Nếu bạn thay đổi phương pháp của bạn để sử dụng NSMutableString
thay vào đó bạn sẽ luôn luôn hoạt động trên cùng dụ và kết quả sẽ do đó một cách chính xác sản lượng 123yyy4xxx
:
func branch() -> NSMutableString {
var str = NSMutableString()
defer { str.appendString("xxx") }
str.appendString("1")
let counter = 3;
if counter > 0 {
str.appendString("2")
defer { str.appendString("yyy") }
str.appendString("3")
}
str.appendString("4")
return str
}
let bran1 = branch()
Trong mã rằng sự trở lại trả về Ví dụ lưu trữ trong str
và trì hoãn thay đổi rằng dụ, nó không gán một cá thể mới nhưng thay đổi một cá thể đã có.
Đối với lời giải thích vì lợi ích bạn có thể thử để xem các địa chỉ bộ nhớ của str
ở các giai đoạn khác nhau:
- tại thời điểm
return
- trước khi thay đổi
str
trong khối defer
- sau khi thay đổi nó
Đối với NSMutableString
cả ba trường hợp sẽ mang lại cùng một địa chỉ bộ nhớ g rằng cá thể vẫn giữ nguyên. Tuy nhiên, String
sẽ in hai địa chỉ bộ nhớ khác nhau dẫn đến Chuỗi được trả lại để trỏ đến someAddress
và một số được hoãn lại để trỏ đến someOtherAddress
.
nó hoạt động nhưng 'defer' được gọi _after_ phạm vi chạy ra ngoài, do đó đầu tiên 'return str' được gọi là sau đó phạm vi chạy ra ngoài và nó gọi' defer' của bạn và thêm '" xxx "' vào cá thể cục bộ xảy ra _after_ giá trị trả về. – holex