2012-08-22 30 views
5

Đây là một phần của một bài tập tuy nhiên tôi chỉ hỏi để làm rõ:C++ mảng năng động mà không STL

tải dữ liệu từ ATM.txt và lưu trữ chúng trong một mảng động (loại ATM, không STL) khi chương trình khởi động.

Tôi làm cách nào để tạo mảng động mà không có STL? Tôi nghĩ có lẽ việc chuyển nhượng có nghĩa là sử dụng con trỏ, "ATM Type" đã ném tôi đi.

Nó đề cập một lần nữa:

tập tin accounts.txt vào một mảng động (loại tài khoản, không STL)

phần --not Hợp đồng chuyển nhượng

Tôi chưa bao giờ hiểu việc sử dụng các thao tác không an toàn cho bộ nhớ, ví dụ: kéo số lượng mục trong một tệp từ dòng đầu tiên:

ví dụ:

5 
abc 
def 
hij 
kml 
mno 

Nó sẽ không thể thông minh hơn để sử dụng STL (vectơ, hoặc C++ 11 mảng) và không phụ thuộc vào số trong nội dung tập tin có thể không chính xác gây ra lỗi tràn bộ đệm vv?

// Sửa Định nghĩa một class Account trong một file Account.h trong đó có các thành viên dữ liệu: khách hàng id, số BSB vv

tôi giả sử tài khoản và các loại máy ATM là những lớp học.

+3

"Nó sẽ không thể thông minh hơn để sử dụng STL" tất nhiên nó sẽ. :) Nhưng nếu đó là một nhiệm vụ, điều này có giá trị giáo dục. –

+0

"Loại ATM" là gì? –

+1

ATM không phải là thuật ngữ chuẩn hoặc nổi tiếng trong C++. Bài tập/khóa học của bạn có định nghĩa nó không? –

Trả lời

4

Các hình thức cơ bản nhất của mảng động là tạo ra sử dụng new[], và phá hủy sử dụng delete[]:

ATM * atms = new ATM[count]; 
// do stuff with the array 
delete [] atms; 

Tuy nhiên, điều này mang lại sự nguy hiểm mà các mã sử dụng mảng có thể ném một ngoại lệ, trở về từ chức năng hoặc ngăn chặn việc xảy ra lỗi delete[]. Nếu điều đó xảy ra, thì bạn sẽ mất con trỏ duy nhất đến bộ nhớ được cấp phát, và nó sẽ vẫn được cấp phát nhưng không thể truy cập được; điều này được gọi là rò rỉ bộ nhớ . Vì lý do này, nó tốt hơn để quấn mảng trong một lớp học, với:

  • biến thành viên để lưu trữ một con trỏ đến mảng, và (tùy chọn) kích thước của nó
  • nhà thầu và/hoặc các chức năng bố trí mảng
  • một destructor xóa mảng
  • (tùy chọn) chức năng (s) để thay đổi kích thước mảng

xóa phân bổ trong destructor của một đối tượng sử dụng theo nguyên tắc RAII để đảm bảo rằng t mảng của anh ta bị xóa một khi nó không còn cần thiết nữa.

Điều này để lại một mối nguy hiểm nữa: nếu bạn sao chép đối tượng mảng này, thì bạn sẽ kết thúc với hai đối tượng cố gắng xóa cùng một mảng, đó là thảm họa. Để ngăn chặn điều này, bạn cần xem xét Rule of Three. Hoặc là viết một hàm tạo bản sao và toán tử gán bản sao để cấp phát một mảng mới và sao chép nội dung; hoặc xóa chúng. (Nếu bạn đang học C++ cũ, thì bạn không thể xóa các hàm thành viên, vì vậy bạn sẽ phải khai báo chúng riêng tư và không thực hiện chúng thay thế).

Nó sẽ không thông minh hơn để sử dụng STL?

Thông thường, có. Nhưng nếu bạn đang học C++, bạn nên hiểu cách quản lý bộ nhớ hoạt động, cũng như cách để thư viện xử lý nó cho bạn. Đó có lẽ là một phần của bài tập này.

+0

Đây là một bài viết rất thông tin, cảm ơn bạn đã giải thích những mối nguy hiểm. Thông thường tôi sử dụng một constructor de để deallocate – user1617478

1

Cách tiếp cận chung cho loại nhiệm vụ này là để mô phỏng hành vi tự động mở rộng của vectơ của riêng bạn. Phân bổ một mảng cho dữ liệu của bạn trên heap, và theo dõi độ dài của nó và số lượng các mục bạn đã lưu trữ trong mảng.

Khi bạn đã điền mảng bằng dữ liệu của mình, hãy mở rộng kích thước tối đa thêm một số tiền và phân bổ mảng mới. Điều này cho phép bạn sao chép dữ liệu từ mảng cũ vào mảng mới, và sau đó tiếp tục thêm các mục cho đến khi bạn hết dung lượng một lần nữa.

+5

Thực tế, cách tiếp cận * phổ biến sẽ là quyết định rằng bạn không bao giờ có nhiều hơn 1024 mục, sử dụng mảng cố định và hy vọng điều tốt nhất ;-) –

+0

Có ai thực sự làm điều này trong sản xuất không? Hay đây là một cách học cách nó hoạt động như thế nào? – user1617478

+0

@ user1617478: Rất nhiều người * làm *; nhưng theo ý kiến ​​của tôi không ai trong số họ * nên *. Nhưng nó chắc chắn hữu ích để tìm hiểu cách thức hoạt động của quản lý bộ nhớ và tại sao bạn nên tránh tự mình làm việc đó khi có thể. –

0

Về cơ bản nếu bạn cần triển khai mảng động mà không sử dụng STL, bạn phải xử lý rõ ràng với cấp phát bộ nhớ/deallocation.

Về cơ bản bạn phải:

  • Phân bổ không gian với malloc mảng lần đầu tiên được xây dựng hoặc sử dụng
  • Theo dõi chèn/yếu tố loại bỏ
  • Sử dụng realloc khi bạn đã hoàn thành các không gian được phân bổ
  • Miễn phí không gian được phân bổ khi mảng bị phá hủy

Tất nhiên triển khai một STL tốt như container như std :: vector không phải là một nhiệm vụ dễ dàng (cuối cùng là một bài tập về nhà tốt đẹp!).

  • Tránh càng nhiều càng tốt việc tái phân bổ:

    sau Những gì tôi có thể đề nghị là. Khi không gian được hoàn thành, phân bổ một số không gian hơn để tránh liên tục gọi realloc (xem std :: vector :: reserve)

  • Tránh để tái tạo không gian khi các phần tử bị xóa. Khi bạn đã cấp phát, trừ khi sử dụng bộ nhớ quá cao, hãy để khoảng trống được phân bổ như vậy, để tránh việc phân bổ lại trong tương lai.
+0

Tôi đã luôn luôn nghĩ rằng bộ nhớ quản lý vector hiệu quả hơn nhiều so với cơ bản khi làm đầy đủ một mảng lớn hơn và sao chép nó hơn. – user1617478

+0

@ user1617478: Vì bộ nhớ của vectơ phải là một khối liền kề duy nhất, đó là cách duy nhất để quản lý nó. Nó làm cho nó hiệu quả nhất có thể bằng cách phát triển theo cấp số nhân (làm giảm số lượng các phân bổ lại khi nó phát triển), và cho phép bạn dự trữ không gian để tránh tái phân bổ. –

0

Nó sẽ không thể thông minh hơn để sử dụng STL (vectơ, hoặc C++ 11 mảng) và không dựa vào số trong nội dung tập tin có thể không chính xác gây tràn bộ đệm vv?

Nội bộ của tiêu chuẩn :: vector không phải là ma thuật. Có thể tự làm những gì std :: vector làm cho bạn.

Có vẻ như đó là những gì bạn phải làm cho nhiệm vụ này; tạo 'loại ATM' của riêng bạn có thể quản lý dữ liệu đọc một cách an toàn từ tệp ATM.txt và 'Loại tài khoản' có thể chứa dữ liệu từ tệp accounts.txt. Bạn có lẽ nên nhận được một số làm rõ từ bất cứ ai đã viết bài tập về cách chính xác họ mong đợi các loại được thiết kế/sử dụng. Ngoài ra nhìn lại bất kỳ tài liệu lớp học bạn có nên cho bạn biết những gì bạn cần biết về sử dụng mảng năng động.

-1

Do đây là bài tập về nhà, chúng tôi không muốn đưa ra câu trả lời trực tiếp, nhưng nhìn chung những gì tôi đề nghị là:

  1. Tạo một lớp myDynamicArray
  2. Làm cho lớp chứa một int hoặc dài để lưu trữ mảng kích thước
  3. Phân bổ bộ nhớ cho mảng của bạn bằng cách sử dụng "mới". Từ bài tập, có vẻ như nó có thể là một chuỗi các chuỗi hoặc, nếu giáo sư nghiêm cấm việc STL (chuỗi bây giờ được coi là STL), nó sẽ là một mảng các mảng ký tự.
  4. Viết phương thức chèn, trước khi chèn, kiểm tra kích thước (xem # 2) của mảng của bạn và nếu nó không đủ lớn, hãy làm cho nó lớn hơn. Một cách để làm điều này mà không sử dụng các hàm trước C++, mà tôi cho là tốt nhất vì đây là một lớp C++, là cấp phát một mảng mới có kích thước lớn hơn -> sao chép dữ liệu từ mảng cũ -> Chèn bất kỳ dữ liệu mới nào. Lớn hơn bao nhiêu? Bạn có thể chọn, nói, lớn hơn 20% với mỗi phân bổ mới. C# của Microsoft phân bổ "số nguyên tố lớn nhất tiếp theo" của các phần tử, mặc dù chúng có các thói quen cấp phát bộ nhớ thực sự nhanh.
  5. Đừng quên xóa() mảng động khi kết thúc với nó (những gì "đã hoàn thành" có nghĩa là phụ thuộc vào bài tập). Lưu ý rằng một khi chương trình thoát, về mặt kỹ thuật bộ nhớ sẽ được giải phóng tự động, nhưng thực tế rất xấu để không tự giải phóng bản thân (nghĩ các chương trình lớn hơn, không học thuật thường không bị tắt).

Tôi muốn tránh mã mẫu mà người dùng khác đã cung cấp. Tôi chắc chắn đó là mã tuyệt vời, nhưng nó sẽ nâng cao một lông mày để sử dụng cái gì đó tiên tiến trong một lớp C++ đầu.

đọc Đề xuất: http://www.cplusplus.com/doc/tutorial/dynamic/

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