2010-04-02 8 views
16

Tôi đã thấy một câu hỏi ngày hôm qua đã nêu lên (đối với tôi) một câu hỏi khác. Vui lòng xem mã sau:Các trường của lớp, chúng có được lưu trữ trong ngăn xếp hoặc đống không?

public class Class1 
{ 
    int A; //as I uderstand, int is value type and therefore lives in the stack 
} 

class Class2 
{ 
    Run() 
    { 
     Class1 instance1 = new Class1(); 
     instance1.A = 10; //it points to value type, but isnt this reference (on heap)? 
    } 
} 

Hoặc trong khi tạo cá thể của Class1, các kiểu trường của nó cũng được tạo trên heap? Nhưng sau đó tôi không hiểu khi nào nó thực sự sẽ được trên stack như hầu như luôn luôn bạn cần phải tạo ra một thể hiện của đối tượng để sử dụng các lĩnh vực.

+0

Tên lớp không được phép bắt đầu bằng số – cpalmer

+0

ngoài chủ đề: bạn có tên lớp không hợp lệ ở đó – thelost

+0

cảm ơn, đã sửa :) – Mirek

Trả lời

3

Biến cấu trúc cục bộ (loại giá trị) được lưu trữ trên ngăn xếp, các trường loại giá trị của một lớp được lưu trữ trên heap.

+7

Trừ khi (1) biến cục bộ là địa chỉ bên ngoài đóng của một phương thức ẩn danh hoặc biểu thức lambda, hoặc (2) địa phương nằm trong khối lặp, hoặc (3) jitter quyết định sử dụng thanh ghi thay vì ngăn xếp. –

+0

những gì xảy ra với biến thể instance1 đến mức lưu trữ của nó là có liên quan. Nó là một kiểu tham chiếu nhưng đồng thời nó là cục bộ của hàm Run(). Sẽ instance1 được lưu trên stack hoặc heap? – RBT

+0

Tôi xin lỗi @EricLippert cho một nhận xét khác nhưng tôi đã cố gắng chỉnh sửa bài viết trước của mình nhưng không thể làm điều đó kịp thời. Chỉ cần thêm sự rõ ràng cho câu hỏi của tôi ở trên tôi muốn hỏi hai điều 1. nơi mà instance1 tham chiếu sẽ được lưu lại. instance1 chỉ là một tham chiếu giữ một địa chỉ bộ nhớ đến nơi mà cá thể đối tượng thực sự đang cư trú 2. nơi đối tượng, thể hiện của Class1 được gọi bởi instance1 sẽ cư trú. Ở đây đối tượng là một thể hiện của Class1 nhưng có một phạm vi cục bộ trong phương thức Run(). – RBT

2

Ok int là một loại giá trị nhưng '1' (tên thật là khủng khiếp của một lớp) là loại tham chiếu. Điều này có nghĩa là bất kỳ trường hợp nào của '1' đều nằm trên vùng heap.

36

như tôi hiểu, int là kiểu giá trị và do đó sống trong ngăn xếp

hiểu biết của bạn là không chính xác. Các loại giá trị được gọi là "loại giá trị" vì chúng được sao chép theo giá trị. Các loại tham chiếu được gọi là "loại tham chiếu" vì chúng được sao chép theo tham chiếu. Nó không phải là ở tất cả các sự thật rằng "loại giá trị luôn luôn sống trên ngăn xếp". Nếu điều đó đúng, chúng sẽ được gọi là "loại ngăn xếp" và "loại đống".

Sự thật là đây là chi tiết triển khai. Việc triển khai khung công tác khác nhau có thể chọn sử dụng ngăn xếp và vùng heap theo ý muốn. Dưới đây là cách triển khai của Microsoft thực hiện:

  • giá trị của một loại tham chiếu là tham chiếu đến bộ nhớ heap. Tham chiếu về cơ bản là số nguyên 32 bit hoặc 64 bit.
  • giá trị của một biến loại giá trị là giá trị của nó.
  • giá trị của biến địa phương được lưu trữ trên ngăn xếp trừ khi biến cục bộ nằm trong khối lặp hoặc được đóng trên các biến bên ngoài của một phương thức ẩn danh hoặc biểu thức lambda. Trong những trường hợp đó, các giá trị của các biến cục bộ được lưu trữ trên heap. Trừ khi tất nhiên các biến địa phương có thể được tối ưu hóa đi, trong trường hợp đó không có lưu trữ nào cả. Hoặc có lẽ họ có thể được đăng ký, trong trường hợp đó họ không phải là trên stack hay heap, họ đang ở trong bộ xử lý đăng ký.
  • giá trị của các biến mẫu của loại tham chiếu và biến tĩnh được lưu trữ trên heap.

Điều đó có rõ ràng không?

nó trỏ đến loại giá trị, nhưng không phải là tham chiếu này (trên heap)?

Trường "A" có loại giá trị. Nó là một trường, và do đó biến đó được lưu trữ trên heap.

trong khi tạo cá thể của Class1, các kiểu trường của nó cũng được tạo trên heap?

Bộ nhớ cho các biến mẫu là trên đống, có.

Nhưng sau đó tôi không hiểu khi nào nó thực sự ở trên ngăn xếp vì hầu như lúc nào bạn cũng cần phải tạo một thể hiện đối tượng để sử dụng các trường đó.

Nó sẽ không bao giờ ở trên ngăn xếp. Như tôi đã nói ở trên, những thứ duy nhất trên stack là các biến cục bộ (và các thời gian tạm thời do trình biên dịch tạo ra) mà không phải là các địa phương đóng của một lambda hoặc phương thức ẩn danh và không nằm trong khối lặp. Và tất nhiên, jitter là miễn phí để giữ chúng ra khỏi ngăn xếp hoàn toàn và đặt chúng trong sổ đăng ký nếu có đăng ký miễn phí.

Nhưng thực sự, tôi phải hỏi, tại sao bạn quan tâm những gì xảy ra trên ngăn xếp và những gì diễn ra trên heap? Những gì xảy ra trên stack là những thứ chúng ta có thể đặt giá rẻ trên stack; mọi thứ khác đi trên heap.

+0

Tôi đã có cuốn sách từ John Sharp nói rằng "Các loại giá trị được tạo trên ngăn xếp trong khi các loại tham chiếu trên heap". Không hiểu nó, quá. – Thomas

+0

"giá trị của ví dụ và biến tĩnh được lưu trữ trên heap." Ngoại trừ các biến mẫu cấu trúc kiểu của một cá thể đã được lưu trữ trên ngăn xếp, phải không? – Joren

+2

"tại sao bạn quan tâm đến những gì xảy ra trên đống và những gì xảy ra trên đống" - bởi vì một số người phỏng vấn rất thích những câu hỏi như vậy và rất nhiều người đã thất bại vì cuộc phỏng vấn được viết ở mọi nơi mà các biến int luôn được lưu trữ trên ngăn xếp chứ không phải "những thứ duy nhất có trên ngăn xếp là các biến cục bộ" – Laserson