Mảng so với Vectơ: Sự giống và khác biệt giới thiệu [đã đóng]


111

Sự khác biệt giữa mảng và vectơ trong C ++ là gì? Ví dụ về sự khác biệt có thể bao gồm thư viện, biểu tượng, khả năng, v.v.

Mảng

Mảng chứa một số phần tử cụ thể của một kiểu cụ thể. Để trình biên dịch có thể dự trữ lượng không gian cần thiết khi chương trình được biên dịch, bạn phải chỉ định kiểu và số phần tử mà mảng sẽ chứa khi nó được xác định. Trình biên dịch phải có khả năng xác định giá trị này khi chương trình được biên dịch. Khi một mảng đã được xác định, bạn sử dụng số nhận dạng cho mảng cùng với một chỉ mục để truy cập các phần tử cụ thể của mảng. Mảng [...] được lập chỉ mục bằng 0; nghĩa là, phần tử đầu tiên ở chỉ số 0. Lược đồ lập chỉ mục này biểu thị mối quan hệ chặt chẽ trong C ++ giữa con trỏ và mảng cũng như các quy tắc mà ngôn ngữ định nghĩa cho số học con trỏ.

- Tham khảo bỏ túi C ++

Véc tơ

Vectơ là một chuỗi các đối tượng có kích thước động cung cấp operator[]quyền truy cập ngẫu nhiên kiểu mảng . Hàm thành viên push_backsao chép các đối số của nó thông qua hàm tạo bản sao, thêm bản sao đó làm mục cuối cùng trong vectơ và tăng kích thước của nó lên một.pop_backhoàn toàn ngược lại, bằng cách loại bỏ phần tử cuối cùng. Việc chèn hoặc xóa các mục khỏi phần cuối của vectơ sẽ mất thời gian không đổi được khấu hao và việc chèn hoặc xóa khỏi bất kỳ vị trí nào khác sẽ mất thời gian tuyến tính. Đây là những điều cơ bản về vectơ. Còn rất nhiều thứ khác nữa. Trong hầu hết các trường hợp, một vectơ phải là lựa chọn đầu tiên của bạn trên một mảng kiểu C. Trước hết, chúng có kích thước linh hoạt, có nghĩa là chúng có thể phát triển khi cần thiết. Bạn không cần phải thực hiện tất cả các loại nghiên cứu để tìm ra kích thước tĩnh tối ưu, như trong trường hợp của mảng C; một vectơ phát triển khi cần thiết và nó có thể được thay đổi kích thước lớn hơn hoặc nhỏ hơn theo cách thủ công nếu bạn cần. Thứ hai, vectơ cung cấp kiểm tra giới hạn với athàm thành viên (nhưng không phải vớioperator[]), để bạn có thể làm gì đó nếu bạn tham chiếu đến một chỉ mục không tồn tại thay vì chỉ xem chương trình của bạn gặp sự cố hoặc tệ hơn là tiếp tục thực thi với dữ liệu bị hỏng.

- Sách dạy nấu ăn C ++


Sự khác biệt cơ bản nhất: có những mục đích mà vectơ là một lựa chọn tốt.
Jerry Coffin

1
"toàn bộ" và "khuyết điểm" là trực giao. Nghĩa là, cái này không những không ám chỉ cái kia, mà thậm chí chúng còn không ở cùng một quy mô.
Các cuộc đua ánh sáng trong quỹ đạo

2
Tôi thực sự khó chịu với mọi người rằng những câu hỏi gần giống chính xác là thông tin tôi đang tìm kiếm. Điều này xảy ra quá thường xuyên.
Robert Tamlyn

Câu trả lời:


142

mảng:

  • là một cấu trúc ngôn ngữ nội tại;
  • đến gần như không sửa đổi từ C89;
  • chỉ cung cấp một chuỗi các phần tử liền kề, có thể lập chỉ mục ; không có chuông và còi;
  • có kích thước cố định; bạn không thể thay đổi kích thước một mảng trong C ++ (trừ khi đó là một mảng POD và nó được cấp phát bằng malloc);
  • kích thước của chúng phải là một hằng số thời gian biên dịch trừ khi chúng được cấp phát động;
  • chúng chiếm không gian lưu trữ tùy thuộc vào phạm vi mà bạn khai báo chúng;
  • nếu được phân bổ động, bạn phải phân bổ chúng một cách rõ ràng;
  • nếu chúng được phân bổ động, bạn chỉ nhận được một con trỏ và bạn không thể xác định kích thước của chúng; nếu không, bạn có thể sử dụng sizeof(do đó là thành ngữ phổ biến sizeof(arr)/sizeof(*arr), tuy nhiên không thành công khi vô tình được sử dụng trên một con trỏ);
  • tự động phân rã thành một con trỏ trong hầu hết các tình huống; đặc biệt, điều này xảy ra khi chuyển chúng đến một hàm, thường yêu cầu chuyển một tham số riêng cho kích thước của chúng;
  • không thể được trả về từ một hàm;
  • không thể sao chép / gán trực tiếp;
  • mảng động của các đối tượng yêu cầu một hàm tạo mặc định, vì tất cả các phần tử của chúng phải được xây dựng trước;

std::vector:

  • là một lớp mẫu;
  • là một cấu trúc chỉ C ++;
  • được thực hiện dưới dạng một mảng động ;
  • lớn lên và co lại một cách linh động;
  • tự động quản lý bộ nhớ của họ, được giải phóng khi bị phá hủy;
  • có thể được chuyển đến / trả về từ các hàm (theo giá trị);
  • có thể được sao chép / gán (điều này thực hiện sao chép sâu của tất cả các phần tử được lưu trữ);
  • không phân rã thành con trỏ, nhưng bạn có thể nhận được một cách rõ ràng một con trỏ tới dữ liệu của chúng ( &vec[0]được đảm bảo hoạt động như mong đợi);
  • luôn mang theo mảng động bên trong kích thước của nó (bao nhiêu phần tử hiện được lưu trữ) và dung lượng (bao nhiêu phần tử có thể được lưu trữ trong khối hiện được cấp phát);
  • mảng động nội bộ không được cấp phát bên trong bản thân đối tượng (chỉ chứa một vài trường "kế toán"), nhưng được cấp phát động bởi trình cấp phát được chỉ định trong tham số mẫu có liên quan; cái mặc định lấy bộ nhớ từ freestore (cái gọi là đống), độc lập với cách mà đối tượng thực được cấp phát;
  • vì lý do này, chúng có thể kém hiệu quả hơn các mảng "thông thường" đối với các mảng cục bộ nhỏ, tồn tại trong thời gian ngắn;
  • khi phân bổ lại, các đối tượng được sao chép (di chuyển, trong C ++ 11);
  • không yêu cầu một phương thức khởi tạo mặc định cho các đối tượng đang được lưu trữ;
  • được tích hợp tốt hơn với phần còn lại của cái gọi là STL (nó cung cấp begin()/ end()các phương thức, các STL thông thường typedef, ...)

Cũng xem xét "thay thế hiện đại" cho mảng - std::array; Tôi đã mô tả trong một câu trả lời khác về sự khác biệt giữa std::vectorstd::array, bạn có thể muốn xem xét nó.


1
Cảm ơn bạn, @MatteoItalia. Một hoặc hai tài liệu tham khảo sẽ rất tốt.
Trancot

1
@Trancot: bất kỳ cuốn sách C ++ hay nào cũng được.
Matteo Italia

6
@Trancot: Tôi thực sự không thể cung cấp cho bạn nhiều tài liệu tham khảo tốt hơn - sự khác biệt được nêu bật trong bài đăng này đến từ nhiều phần khác nhau của Tiêu chuẩn và được hiểu rõ hơn với sự trợ giúp của một sách hướng dẫn C ++ tốt.
Matteo Italia

Một ví dụ về mô tả bao quát như vậy sẽ rất tuyệt!
carloswm85,

26

Tôi sẽ nói thêm rằng mảng là những cấu trúc cấp thấp trong C ++ và bạn nên cố gắng tránh xa chúng càng nhiều càng tốt khi "học theo dây" - ngay cả Bjarne Stroustrup cũng khuyến nghị điều này (anh ấy là nhà thiết kế của C ++).

Vectơ có cùng hiệu suất như mảng, nhưng có nhiều tiện ích và tính năng an toàn tuyệt vời. Bạn có thể sẽ bắt đầu sử dụng mảng khi giao tiếp với API xử lý mảng thô hoặc khi xây dựng bộ sưu tập của riêng bạn.


1
Giao diện chương trình ứng dụng: ( en.wikipedia.org/wiki/API ). Nó là một tập hợp các điểm vào một thực thể phần mềm (gói, thư viện, hệ điều hành). Một số API sẽ có các điểm đầu vào như strcat (char * dst, char * src), trong đó dst và src được coi là mảng ký tự (mặc dù chữ ký hàm ngụ ý con trỏ đến ký tự).
John Källén

11

Những tài liệu tham khảo đã trả lời khá nhiều câu hỏi của bạn. Nói một cách đơn giản, độ dài của vectơ là động trong khi mảng có kích thước cố định. khi sử dụng một mảng, bạn chỉ định kích thước của nó khi khai báo:

int myArray[100];
myArray[0]=1;
myArray[1]=2;
myArray[2]=3;

đối với vectơ, bạn chỉ cần khai báo nó và thêm các phần tử

vector<int> myVector;
myVector.push_back(1);
myVector.push_back(2);
myVector.push_back(3);
...

đôi khi bạn sẽ không biết số lượng phần tử cần thiết để một vectơ sẽ là lý tưởng cho tình huống như vậy.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.