Kể từ khi tồn tại std::list
và std::vector
tồn tại, có lý do gì để sử dụng mảng C truyền thống trong C ++, hay nên tránh chúng, giống như malloc
?
Kể từ khi tồn tại std::list
và std::vector
tồn tại, có lý do gì để sử dụng mảng C truyền thống trong C ++, hay nên tránh chúng, giống như malloc
?
Câu trả lời:
Trong C ++ 11 nếu std::array
có sẵn, câu trả lời là "có, nên tránh các mảng". Trước C ++ 11, bạn có thể cần sử dụng mảng C để cấp phát mảng trong bộ lưu trữ tự động (tức là trên ngăn xếp).
Chắc chắn, mặc dù với std::array
trong C ++ 11, thực tế chỉ dành cho dữ liệu tĩnh. Mảng kiểu C có ba ưu điểm quan trọng hơn
std::vector
:
Chúng không yêu cầu phân bổ động. Vì lý do này, các mảng kiểu C được ưu tiên hơn khi bạn có thể có nhiều mảng rất nhỏ. Nói điều gì đó giống như một điểm thứ nguyên:
template <typename T, int dims>
class Point
{
T myData[dims];
// ...
};
Thông thường, người ta có thể tưởng tượng một dims
sẽ rất nhỏ (2 hoặc 3),
T
một kiểu tích hợp ( double
) và bạn có thể kết thúc
std::vector<Point>
với hàng triệu phần tử. Bạn chắc chắn không muốn hàng triệu phân bổ động là 3 đôi.
Hỗ trợ khởi tạo tĩnh. Đây chỉ là một vấn đề đối với dữ liệu tĩnh, trong đó một số thứ như:
struct Data { int i; char const* s; };
Data const ourData[] =
{
{ 1, "one" },
{ 2, "two" },
// ...
};
Điều này thường thích hợp hơn khi sử dụng một vectơ (và std::string
), vì nó tránh tất cả các vấn đề về thứ tự khởi tạo; dữ liệu được tải trước, trước khi bất kỳ mã thực tế nào có thể được thực thi.
Cuối cùng, liên quan đến những điều trên, trình biên dịch có thể tính toán kích thước thực của mảng từ các trình khởi tạo. Bạn không cần phải đếm chúng.
Nếu bạn có quyền truy cập vào C ++ 11, hãy std::array
giải quyết hai vấn đề đầu tiên và chắc chắn nên được sử dụng ưu tiên cho mảng kiểu C trong trường hợp đầu tiên. Tuy nhiên, nó không giải quyết phần thứ ba và việc có kích thước trình biên dịch cho mảng theo số lượng bộ khởi tạo vẫn là một lý do hợp lệ để thích mảng kiểu C.
int i[] = { 1, 2, 3 };
tiếp tục làm việc với int i[] = { 1, 2, 3, 4 };
. array<int, 3>
cần được thay đổi thủ công thành array<int, 4>
.
make_array
hàm , tương tự như make_pair
v.v. Hat-tip thành @R. Martinho Fernandes .
std::array
trong C ++ 11, [chúng nên được sử dụng] thực tế chỉ cho dữ liệu tĩnh”.
Đừng bao giờ nói "không bao giờ", nhưng tôi đồng ý rằng vai trò của chúng bị giảm đi đáng kể bởi cấu trúc dữ liệu thực sự từ STL.
Tôi cũng muốn nói rằng việc đóng gói bên trong các đối tượng sẽ giảm thiểu tác động của các lựa chọn như thế này. Nếu mảng là thành viên dữ liệu riêng tư, bạn có thể hoán đổi nó vào hoặc ra mà không ảnh hưởng đến các máy khách trong lớp của bạn.
Tôi đã làm việc trên các hệ thống quan trọng về an toàn mà bạn không thể sử dụng phân bổ bộ nhớ động. Bộ nhớ phải luôn ở trên ngăn xếp. Do đó, trong trường hợp này, bạn sẽ sử dụng mảng vì kích thước được cố định tại thời điểm biên dịch.
std::array<T>
phân bổ trên các ngăn xếp và về cơ bản không có chi phí trên một mảng thô.
array
trong c++
cung cấp cho bạn kích thước cố định thay thế nhanh chóng của kích thước động std::vector
và std::list
. std :: array là một trong những phần bổ sung trong c++11
. Nó cung cấp lợi ích của các thùng chứa std trong khi vẫn cung cấp ngữ nghĩa kiểu tổng hợp của các mảng kiểu C.
Vì vậy, c++11
tôi chắc chắn sẽ sử dụng std::array
, khi nó được yêu cầu, trên vector. Nhưng tôi sẽ tránh mảng kiểu C trong C++03
.
Thông thường, không , tôi không thể nghĩ ra lý do để sử dụng các mảng thô vectors
. Nếu mã là mới .
Bạn có thể phải sử dụng mảng nếu thư viện của bạn cần tương thích với mã yêu cầu mảng và con trỏ thô.
vector.data()
trong C ++ 11 hoặc &vector.front()
trước đó.
Tôi biết rất nhiều người đang chỉ ra std :: array để cấp phát mảng trên ngăn xếp và std :: vector cho heap. Nhưng dường như không hỗ trợ căn chỉnh không phải gốc. Nếu bạn đang thực hiện bất kỳ loại mã số nào mà bạn muốn sử dụng hướng dẫn SSE hoặc VPX (do đó yêu cầu căn chỉnh 128 hoặc 256 byte tương ứng), mảng C dường như vẫn là lựa chọn tốt nhất của bạn.
Tôi sẽ nói rằng các mảng vẫn hữu ích, nếu bạn đang lưu trữ một lượng nhỏ dữ liệu tĩnh tại sao lại không.
Ưu điểm duy nhất của một mảng (tất nhiên được bao bọc trong thứ gì đó sẽ tự động quản lý vị trí giao dịch của nó khi cần) std::vector
mà tôi có thể nghĩ đến là vector
không thể chuyển quyền sở hữu dữ liệu của nó, trừ khi trình biên dịch của bạn hỗ trợ C ++ 11 và di chuyển các hàm tạo.
swap
.
Mảng kiểu C là một cấu trúc dữ liệu cơ bản, vì vậy sẽ có những trường hợp tốt hơn khi sử dụng nó. Tuy nhiên, đối với trường hợp chung, hãy sử dụng cấu trúc dữ liệu nâng cao hơn để làm tròn các góc của dữ liệu cơ bản. C ++ cho phép bạn làm một số điều rất thú vị và hữu ích với bộ nhớ, nhiều trong số đó hoạt động với các mảng đơn giản.
std::array
s như thế nào? Trong nhiều trường hợp, cả hai sẽ được biên dịch vào cùng một assembly.
std::array
có ngữ nghĩa được xác định chính xác được xây dựng trên đầu các mảng tĩnh.
Bạn nên sử dụng các vùng chứa STL bên trong, nhưng bạn không nên chuyển con trỏ đến các vùng chứa như vậy giữa các mô-đun khác nhau, nếu không bạn sẽ rơi vào địa ngục phụ thuộc. Thí dụ:
std::string foo;
// fill foo with stuff
myExternalOutputProc(foo.c_str());
là một giải pháp rất tốt nhưng không
std::string foo;
// fill foo with stuff
myExternalOutputProc(&foo);
Lý do là vì chuỗi std :: có thể được thực hiện theo nhiều cách khác nhau nhưng một chuỗi c-style luôn là một chuỗi c-style.