2008-10-13 5 views
22

Tôi luôn tự hỏi liệu có toán tử để xóa mảng đa chiều theo ngôn ngữ C++ chuẩn hay không.Tại sao "xóa [] [] ... multiDimensionalArray;" toán tử trong C++ không tồn tại

Nếu chúng ta đã tạo ra một con trỏ đến một mảng chiều đơn

int *array = new int[size]; 

vẻ xóa như:

delete [] array; 

Đó là tuyệt vời. Nhưng nếu chúng ta có hai mảng kích thước, chúng tôi không thể làm

delete [][] twoDimenstionalArray; 

Thay vào đó, chúng ta nên vòng lặp và xóa các mục, như trong ví dụ this.

Ai đó có thể giải thích lý do không?

Trả lời

25

Về mặt kỹ thuật, không có mảng hai chiều trong C++. Những gì bạn đang sử dụng như là một mảng hai chiều là một mảng một chiều với mỗi phần tử là một mảng một chiều. Vì nó không tồn tại về mặt kỹ thuật, C++ không thể xóa nó.

0

xóa [] áp dụng cho bất kỳ phi vô hướng nào (mảng).

+0

Không, bạn sẽ gây ra rò rỉ bộ nhớ nếu bạn cố gắng xóa [] một mảng bị lởm chởm. –

4

không chắc chắn lý do chính xác từ quan điểm thiết kế ngôn ngữ, tôi đoán nó có liên quan đến thực tế khi phân bổ bộ nhớ bạn đang tạo mảng mảng và mỗi mảng cần xóa.

int ** mArr = new int*[10]; 
for(int i=0;i<10;i++) 
{ 
    mArr[i]=new int[10]; 
} 

C++ của tôi bị gỉ, tôi không chắc liệu điều đó có đúng về mặt cú pháp hay không, nhưng tôi nghĩ nó gần đúng.

7

Lý do xóa được gọi nhiều lần trong ví dụ đó là vì mới được gọi nhiều lần. Xóa phải được gọi cho mỗi mới.

Ví dụ: nếu tôi phân bổ 1.000.000 byte bộ nhớ, sau này tôi không thể xóa các mục nhập từ 200.000 - 300,00, nó được phân bổ dưới dạng toàn bộ đoạn và phải được giải phóng toàn bộ đoạn.

+2

Vì vậy, các opposit cũng đúng, nếu nó được phân bổ như nhiều khối nó phải được giải phóng như nhiều khối –

+1

Vâng, quan điểm của tôi chính xác! – KPexEA

20

Bởi vì không có cách nào để gọi

int **array = new int[dim1][dim2]; 

Tất cả các tin tức/xóa phải được cân bằng, vì vậy không có điểm đến một nhà điều hành delete [][].

new int[dim1][dim2] trả về con trỏ tới một mảng có kích thước dim1 loại int[dim2]. Vì vậy, dim2 phải là một hằng số thời gian biên dịch. Điều này tương tự như phân bổ mảng đa chiều trên ngăn xếp.

+1

là cách khác. dim2 phải là một hằng số thời gian biên dịch, trong khi dim1 không cần phải có, và một int (*) [dim2] được trả về :) bạn có thể ghi nhớ cú pháp khi tưởng tượng những gì sẽ xảy ra nếu bạn làm int v [dim1] [dim2 ]; và kiểm tra loại v sau khi phân rã thành con trỏ: đó là int (*) [dim2]; –

6

Lý do bạn phải lặp lại, như trong ví dụ bạn đề cập, là số lượng mảng cần được xóa không được biết đến trình biên dịch/cấp phát.

Khi bạn phân bổ mảng hai chiều của mình, bạn thực sự đã tạo mảng N một chiều. Bây giờ mỗi người trong số đó phải bị xóa, nhưng hệ thống không biết có bao nhiêu trong số đó. Kích thước của mảng cấp cao nhất, tức là mảng con trỏ tới mảng thứ hai của bạn, giống như bất kỳ mảng nào khác trong C: kích thước của nó không được hệ thống lưu trữ.

Do đó, không có cách nào để triển khai delete [][] khi bạn mô tả (mà không thay đổi đáng kể ngôn ngữ).

0

Bạn có thể sử dụng lớp trình bao bọc để thực hiện tất cả những điều đó cho bạn. Làm việc với các kiểu dữ liệu "nguyên thủy" thường không phải là một giải pháp tốt (các mảng nên được đóng gói trong một lớp). Ví dụ std :: vector là một ví dụ rất hay thực hiện điều này.

Xóa phải được gọi chính xác số lần gọi mới. Vì bạn không thể gọi "a = new X [a] [b]", bạn cũng không thể gọi "delete [] [] a".

Về mặt kỹ thuật, đó là một quyết định thiết kế tốt ngăn cản sự xuất hiện của khởi tạo lạ của toàn bộ ma trận n chiều.

0

Vâng, tôi nghĩ rằng nó rất dễ thực hiện, nhưng quá nguy hiểm. Nó rất dễ dàng để cho biết liệu một con trỏ được tạo ra bởi new[], nhưng khó có thể nói về new[]...[] (nếu được phép).

3

Trong khi tất cả những câu trả lời phù hợp, tôi sẽ cố gắng giải thích những gì đến một kỳ vọng, rằng một cái gì đó giống như delete[][] array; có thể làm việc trên mảng cấp phát động và tại sao nó không thể:

Cú pháp int array[ROWS][COLS]; phép trên tĩnh mảng được phân bổ chỉ là trừu tượng đối với các lập trình viên, mà trong thực tế tạo mảng một chiều int array[ROWS*COLS];. Nhưng trong quá trình biên dịch (khi kích thước kích thước COLSROWS phải là hằng số theo chuẩn), trình biên dịch cũng nhớ kích thước của các tham số đó, cần thiết để giải quyết các yếu tố sau này bằng cú pháp, ví dụ: array[x][y] = 45. Trình biên dịch, được biết đến với kích thước này, sau đó sẽ thay thế [x][y] bằng chỉ mục tương ứng thành mảng một chiều bằng cách sử dụng phép toán đơn giản: [COLS*x + y].

Mặt khác, đây không phải là trường hợp với động mảng được phân bổ, nếu bạn muốn có cùng chức năng đa chiều (trong ký hiệu thực tế). Vì kích thước của chúng có thể được xác định trong thời gian chạy, chúng sẽ phải nhớ kích thước của mỗi chiều bổ sung để sử dụng sau này - và hãy nhớ rằng cho toàn bộ vòng đời của mảng. Hơn nữa, các thay đổi hệ thống sẽ phải được thực hiện ở đây để làm việc với các mảng thực sự là đa chiều, để lại dạng ký hiệu truy cập [x][y] trong mã, chứ không thay thế nó bằng ký hiệu một chiều trong khi biên dịch, nhưng sau đó thay thế nó trong thời gian chạy.

Do đó một vắng mặt của array = new int[ROWS][COLS] ngụ ý không cần thiết cho delete[][] array;. Và như đã đề cập, nó không thể được sử dụng trên ví dụ của bạn để xóa mảng "đa chiều" của bạn, bởi vì các mảng phụ của bạn (thứ nguyên bổ sung) được phân bổ riêng biệt (sử dụng riêng biệt gọi new), vì vậy chúng độc lập với đầu mảng (array_2D) có chứa chúng và tất cả chúng không thể bị xóa cùng một lúc.