2013-07-11 37 views
6

Tôi đang đọc lên trên mảng C# vì vậy câu hỏi của tôi là ban đầu trên mảng.Việc khai báo và instantiating một mảng C# thực sự có ý nghĩa gì?

Tuyên bố một mảng thực sự có ý nghĩa gì? Tôi biết bạn khai báo một biến kiểu mảng. Khi tôi có những điều sau đây, những gì đang thực sự xảy ra?

int[] values; 

Có trong bộ nhớ vào thời điểm được khai báo không? Nếu không thì nó ở đâu? Là mảng thực sự tạo ra ở đây?

Sau đó, tôi đi và nhanh chóng một mảng và khởi nó với một số giá trị như:

int[] values = new int[] { 1, 2, 3 }; 

Điều này thực sự đi và tạo mảng bây giờ? Tôi đã đọc rằng mảng được tạo ra khi chúng được khai báo, những người khác nói rằng mảng được tạo ra khi chúng được khởi tạo. Tôi đang cố gắng để có được thuật ngữ của tôi đúng.

Tương tự với biến số nguyên. Nếu tôi có:

int value; 

int value = 1; 

Khi được int tạo? Khi nào nó được thêm vào bộ nhớ?

Xin lỗi vì câu hỏi ngớ ngẩn. Tôi hiểu khái niệm này nhưng muốn biết kỹ thuật đằng sau hậu trường của mảng.

Trả lời

6

Tuyên bố một mảng thực sự có ý nghĩa gì?

Bạn không thực sự khai báo mảng, bạn đã khai báo mảng tham chiếu . Big deal trong .NET, sự khác biệt giữa các kiểu tham chiếu và kiểu giá trị là quan trọng. Chỉ cần có biến tham chiếu mảng là không đủ, cần thêm một bước để tạo đối tượng mảng. Yêu cầu từ khóa mới mới. Mà vật lý phân bổ lưu trữ cho các đối tượng mảng ở nơi mà các đối tượng kiểu tham chiếu được lưu trữ, đống rác thu thập được.

Cũng vậy với một số nguyên biến

Không, sự khác biệt lớn. Đó là một loại giá trị. Nếu nó không phải là một lĩnh vực của một lớp, không phải là rõ ràng từ câu hỏi của bạn, sau đó nó là một biến địa phương của một phương pháp. Nó được tạo ra khi phương thức bắt đầu chạy và poof ra khỏi sự tồn tại khi phương thức trả về. Tối ưu hóa rất cao, lý do cốt lõi mà các loại giá trị tồn tại trong C#. Vị trí lưu trữ vật lý thường là một thanh ghi cpu hoặc một khe trên khung ngăn xếp nếu phương thức sử dụng quá nhiều biến cục bộ.

Nếu nó thực sự là thành viên của một lớp thì nó sẽ được tạo khi đối tượng lớp được tạo. Cũng giống như một mảng, trên heap GC với từ khóa mới mới.

+1

Nếu bạn sử dụng nó theo nghĩa đen, từ khóa 'new' không cần thiết để tạo một đối tượng mảng , bạn cũng có thể viết một cái gì đó như 'int [] values ​​= {1, 2, 3};'. Mặc dù bạn có thể xem đó chỉ là một lối tắt cho cú pháp đầy đủ với 'new'. – svick

+0

@Hans: Việc khai báo tham chiếu mảng có chiếm bất kỳ bộ nhớ nào không? Hoặc chỉ khi mảng được tạo ra? –

+0

Nó có kích thước của một con trỏ. 4 byte trong quy trình 32 bit, 8 byte trong quy trình 64 bit. Dung lượng cho tham chiếu tuân theo các quy tắc giống như quy tắc cho giá trị loại giá trị. –

1
int[] values; 

Có nghĩa là bạn khai báo biến kiểu int []. Chưa có bộ nhớ nào bị chiếm đóng, chỉ có một tham chiếu được tạo. Đoạn mã trên được khởi tạo thành tham chiếu null.

int[] values = new int[] { 1, 2, 3 }; 

Mã này khai báo biến kiểu int [] và tạo ngay một mảng. Biến tham chiếu mảng mới được tạo.

Số nguyên hoạt động hơi khác một chút do chúng là loại giá trị. Các loại giá trị được khởi tạo thành giá trị mặc định của chúng, trong trường hợp các số nguyên, giá trị 0.

Nếu bạn tách khai báo và khởi tạo, điều sau xảy ra.

// This declares a variable 
int[] values; 
// This creates the array, and initializes the variable with the newly created array. 
values = new int[] { 1, 2, 3 }; 
+1

Bạn chỉ tạo tham chiếu null cho 'int []' nếu đó là thành viên của một loại và khi một thể hiện của loại đó được tạo. Nếu bạn làm điều đó bên trong một phương pháp bạn thậm chí không có một tham chiếu cho đến khi bạn khởi tạo nó. – Renan

+0

@Renan Tôi không chắc chắn ý của bạn là gì. Tham chiếu null không phải là thành viên của bất kỳ loại nào (http://ericlippert.com/2013/05/30/what-the-meaning-of-is-is/). – Maarten

+0

"Không có bộ nhớ nào bị chiếm đóng, chỉ một tham chiếu được tạo." Bạn đang nói tham chiếu không chiếm bất kỳ bộ nhớ nào? – svick

1

Khi bạn khai báo một mảng, trong nội bộ tất cả những gì được tạo ra là một con trỏ null đó là loại int[]. Khi bạn sử dụng từ khóa new như trong ví dụ của mình hoặc bạn sử dụng new int[6], tại thời điểm đó, hệ thống sẽ cấp phát bộ nhớ cho kích thước của mảng.

Khai báo một int thực sự sẽ tạo ra bộ nhớ cho các số nguyên với giá trị mặc định là 0.

+1

C# hoạt động giống nhau, vì 'int' là một kiểu giá trị, xem tại đây: http://msdn.microsoft.com/en-us/library/s1ax56ch.aspx.Trích dẫn: * Không giống như các loại tham chiếu, một loại giá trị không thể chứa giá trị null. (...) Mỗi ​​loại giá trị có một hàm tạo ngầm mặc định khởi tạo giá trị mặc định của kiểu đó. * – Treb

+0

Đoạn thứ hai của bạn không chính xác. int là một loại giá trị mặc định bằng không. Hãy thử điều này: 'void Main() {Console.WriteLine (new X(). I);} lớp X {public int i;}' – spender

+0

Cảm ơn bạn đã sửa. Tôi nghĩ tôi đã đọc ở đâu đó rằng 'int' là một bí danh cho 'Int32' hay cái gì đó. – Samuel

1

Khi bạn khai báo nó như thế này:

int[] values; 

bạn không chỉ định kích thước, do đó, không có cách nào để biết bao nhiêu bộ nhớ sẽ cần thiết cho một instatiation.Thông tin này chỉ được đưa ra trong các dòng sau: Yêu cầu

values = new int[] { 1, 2, 3 }; 

Bộ nhớ được suy luận từ số lượng giá trị instatiation (và từ yêu cầu bộ nhớ của các loại int, tất nhiên).

Khi bạn khai báo một int như thế này: Yêu cầu

int value; 

bộ nhớ được biết đến và không thể thay đổi (kể từ int là một kiểu giá trị). Biến này có thể (và sẽ) được tạo ngay lập tức. Nếu bạn không chỉ định giá trị ban đầu, giá trị mặc định sẽ có giá trị mặc định là int0.

+0

Bạn có nói rằng nếu bạn chỉ viết 'int [] giá trị', thì bộ nhớ cho * biến * đó không được cấp phát? Đó là sai, bởi vì biến đó chứa một tham chiếu và bộ nhớ cho rằng * được * phân bổ. – svick

+0

Ngoài ra, nó không có ý nghĩa để nói về giá trị mặc định của biến địa phương, họ không có bất kỳ. Ví dụ, bạn không thể viết 'int i; Console.WriteLine (i); '. – svick

+0

@svick: Số bình luận của bạn 1: Tôi đã không thể hiện bản thân mình đủ rõ ràng, tôi có nghĩa là bộ nhớ ** cho mảng ** không được cấp phát. Nhận xét của bạn số 2: 'int', giống như tất cả các loại giá trị, * có * một giá trị mặc định. Trình biên dịch C# không cho phép bạn sử dụng một biến ** bạn ** chưa được khởi tạo trước đó, đó là chính xác. Nhưng 'i' trong ví dụ của bạn là ** tự động ** được khởi tạo thành giá trị mặc định của nó, tức là 0. Bạn có thể ví dụ như kiểm tra điều này trong trình gỡ rối. Thay thế 'Console.WriteLine (i);' bằng 'Console.WriteLine (" bla ");', đặt một điểm ngắt trên dòng đó và kiểm tra 'i', bạn sẽ thấy rằng giá trị của nó là 0. – Treb

Các vấn đề liên quan