std :: mảng so với hiệu suất mảng


84

Nếu tôi muốn xây dựng một mảng rất đơn giản như

int myArray[3] = {1,2,3};

Tôi có nên sử dụng std::arraythay thế không?

std::array<int, 3> a = {{1, 2, 3}};

Ưu điểm của việc sử dụng std :: array so với những cái thông thường là gì? Nó có hiệu suất hơn không? Chỉ dễ dàng hơn để xử lý sao chép / truy cập?


2
xác định mảng đa chiều với std :: sẽ khó
goGud

15
@goGud: Không khó, chỉ là dài dòng hơn.
Mike Seymour

1
Phân rã con trỏ, lấy một tham chiếu, v.v., nhiều điều kỳ lạ về mảng c. Các iterator có thể là một con trỏ trong trường hợp c-mảng và for (auto i = ++std::begin(myArray); . . . có thể thậm chí không biên dịch (có vẻ như là tạm thời loại cơ bản là không thể thay đổi, ít nhất là không có kêu vang 6)
Patrick fromberg

Khởi tạo cũng khác nhau một cách kỳ diệu: struct Direction { int32_t dw; int32_t dh; };static const Direction DIRECTIONS[DIRECTIONS_COUNT] { { -1, 1}, {0,1}, {1,1} , { 1, 0 }, {1,-1}, {0,-1} , {-1,-1}, {-1,0} };biên dịch. Nhưng nếu bạn thay đổi thành std::array<Direction,DIRECTIONS_COUNT>danh sách có cùng bộ khởi tạo, đột nhiên bạn gặp lỗi "quá nhiều bộ khởi tạo". (Cộng đồng VS 2019 với ngôn ngữ = C ++ 17)
BitTickler

Tại sao lại có dấu ngoặc kép trong phần std::arraykhởi tạo?
Marc.2377

Câu trả lời:


101

Ưu điểm của việc sử dụng std::arrayso với những cái thông thường là gì?

Nó có ngữ nghĩa giá trị thân thiện, vì vậy nó có thể được chuyển đến hoặc trả về từ các hàm theo giá trị. Giao diện của nó giúp thuận tiện hơn trong việc tìm kiếm kích thước và sử dụng với các thuật toán dựa trên trình lặp kiểu STL.

Nó có hiệu suất hơn không?

Nó phải giống hệt nhau. Theo định nghĩa, nó là một tập hợp đơn giản chứa một mảng là thành viên duy nhất của nó.

Chỉ dễ dàng hơn để xử lý sao chép / truy cập?

Đúng.


41

A std::arraylà một trình bao bọc rất mỏng xung quanh một mảng kiểu C, về cơ bản được định nghĩa là

template<typename T, size_t N>
class array
{
public:
    T _data[N];
    T& operator[](size_t);
    const T& operator[](size_t) const;
    // other member functions and typedefs
};

Nó là một tập hợp và nó cho phép bạn sử dụng nó gần giống như một kiểu cơ bản (tức là bạn có thể chuyển theo giá trị, gán, v.v., trong khi một mảng C chuẩn không thể được gán hoặc sao chép trực tiếp sang một mảng khác). Bạn nên xem qua một số triển khai tiêu chuẩn (chuyển sang định nghĩa từ IDE yêu thích của bạn hoặc mở trực tiếp <array>), nó là một phần của thư viện tiêu chuẩn C ++ khá dễ đọc và dễ hiểu.


24

std::array được thiết kế dưới dạng trình bao bọc không chi phí cho các mảng C cung cấp cho nó giá trị "bình thường" giống như ngữ nghĩa của các vùng chứa C ++ khác.

Bạn sẽ không nhận thấy bất kỳ sự khác biệt nào về hiệu suất thời gian chạy trong khi bạn vẫn có thể tận hưởng các tính năng bổ sung.

Sử dụng std::arraythay vì int[]mảng kiểu là một ý tưởng hay nếu bạn có C ++ 11 hoặc boost trong tay.


10

Nó có hiệu suất hơn không?

Nó phải giống hệt nhau. Theo định nghĩa, nó là một tập hợp đơn giản chứa một mảng là thành viên duy nhất của nó.

Tình hình có vẻ phức tạp hơn, vì std::arraykhông phải lúc nào cũng tạo ra mã lắp ráp giống hệt nhau so với mảng C tùy thuộc vào nền tảng cụ thể.

Tôi đã thử nghiệm tình huống cụ thể này trên chốt chặn :

#include <array>
void test(double* const C, const double* const A,
          const double* const B, const size_t size) {
  for (size_t i = 0; i < size; i++) {
    //double arr[2] = {0.e0};//
    std::array<double, 2> arr = {0.e0};//different to double arr[2] for some compiler
    for (size_t j = 0; j < size; j++) {
      arr[0] += A[i] * B[j];
      arr[1] += A[j] * B[i];
    }
    C[i] += arr[0];
    C[i] += arr[1];
  }
}

GCCClang tạo ra mã lắp ráp giống hệt nhau cho cả phiên bản C-array và std::arrayphiên bản.

Tuy nhiên, MSVCICPC tạo ra mã lắp ráp khác nhau cho mỗi phiên bản mảng. (Tôi đã kiểm tra ICPC19 với -Ofast-Os; MSVC -Ox-Os)

Tôi không biết tại sao lại như vậy (tôi thực sự mong đợi hành vi giống hệt nhau của std :: array và c-array). Có thể có các chiến lược tối ưu hóa khác nhau được sử dụng.

Nói thêm một chút: Có vẻ như có một lỗi trong ICPC với

#pragma simd 

để vector hóa khi sử dụng mảng c trong một số trường hợp (mã mảng c tạo ra kết quả sai; std::arrayphiên bản hoạt động tốt).

Thật không may, tôi chưa có một ví dụ làm việc tối thiểu cho điều đó, vì tôi đã phát hiện ra vấn đề đó trong khi tối ưu hóa một đoạn mã khá phức tạp.

Tôi sẽ gửi một báo cáo lỗi cho intel khi tôi chắc chắn rằng tôi không chỉ hiểu sai điều gì đó về C-array / std::arrayand #pragma simd.


1
có thể được coi là một lỗi trình biên dịch?
OznOg

8

std::arraycó ngữ nghĩa giá trị trong khi mảng thô thì không. Điều này có nghĩa là bạn có thể sao chép std::arrayvà coi nó như một giá trị nguyên thủy. Bạn có thể nhận chúng theo giá trị hoặc tham chiếu dưới dạng đối số hàm và bạn có thể trả về chúng theo giá trị.

Nếu bạn không bao giờ sao chép a std::array, thì không có sự khác biệt về hiệu suất so với một mảng thô. Nếu bạn cần tạo bản sao thì std::arraysẽ làm đúng và vẫn cho hiệu suất như nhau.

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.