std :: array 대 어레이 성능


84

다음과 같은 매우 간단한 배열을 만들고 싶다면

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

std::array대신 사용해야합니까 ?

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

일반적인 것보다 std :: array를 사용하면 어떤 이점이 있습니까? 더 성능이 좋습니까? 복사 / 액세스 처리가 더 쉽습니까?


2
std ::로 다차원 배열을 정의하는 것은 어려울 것입니다
goGud

15
@goGud : 어렵지 않고 좀 더 장황합니다.
Mike Seymour

1
포인터 붕괴, 참조 등 ... c-array에 대해 많은 것들이 이상합니다. iterator는 c-array의 경우 포인터가 될 수 있으며 for (auto i = ++std::begin(myArray); . . . 컴파일도 할 수 없습니다 (기본 유형의 임시는 적어도 clang 6에서는 변경할 수없는 것 같습니다)
Patrick Fromberg

초기화는 마술 적으로도 다릅니다 : 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} };컴파일됩니다. 그러나 std::array<Direction,DIRECTIONS_COUNT>동일한 초기화 목록으로 변경하면 갑자기 "너무 많은 초기화 프로그램"오류가 발생합니다. (VS 2019 Community with language = C ++ 17)
BitTickler

std::array초기화 에서 이중 대괄호가 사용되는 이유는 무엇 입니까?
Marc.2377

답변:


101

std::array평소보다 사용하면 어떤 이점이 있습니까?

친숙한 값 의미 체계를 가지고 있으므로 값별로 함수로 전달되거나 반환 될 수 있습니다. 인터페이스를 통해 크기를 찾고 STL 스타일 반복기 기반 알고리즘과 함께 사용하는 것이 더 편리합니다.

더 성능이 좋습니까?

정확히 동일해야합니다. 정의에 따라 배열을 유일한 구성원으로 포함하는 단순 집계입니다.

복사 / 액세스 처리가 더 쉽습니까?

예.


41

A std::array는 기본적으로 다음과 같이 정의되는 C 스타일 배열을 둘러싼 매우 얇은 래퍼입니다.

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
};

그것은 집합체 이고, 그것은 당신이 그것을 거의 기본 유형처럼 사용할 수있게 해준다 (즉, 당신은 값으로 전달하고 할당 할 수있는 반면, 표준 C 배열은 다른 배열에 직접 할당되거나 복사 될 수 없다). 몇 가지 표준 구현을 살펴보아야합니다 (좋아하는 IDE에서 정의로 이동하거나 직접 열 수 있음 <array>). 이것은 읽고 이해하기 쉬운 C ++ 표준 라이브러리의 일부입니다.


24

std::array 다른 C ++ 컨테이너의 의미와 같은 "정상"값을 제공하는 C 배열에 대한 제로 오버 헤드 래퍼로 설계되었습니다.

추가 기능을 계속 즐길 수있는 동안에는 런타임 성능의 차이를 느끼지 않아야합니다.

스타일 배열 std::array대신 사용 하는 것은 int[]C ++ 11 또는 부스트가 있다면 좋은 생각입니다.


10

더 성능이 좋습니까?

정확히 동일해야합니다. 정의에 따라 배열을 유일한 구성원으로 포함하는 단순 집계입니다.

std::array특정 플랫폼에 따라 항상 C-array와 동일한 어셈블리 코드를 생성하는 것은 아니기 때문에 상황은 더 복잡해 보입니다 .

나는 godbolt 에서이 특정 상황을 테스트했습니다 .

#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 은 C-array 버전과 버전 모두에 대해 동일한 어셈블리 코드를 생성합니다 std::array.

그러나 MSVCICPC 는 각 어레이 버전에 대해 서로 다른 어셈블리 코드를 생성합니다. (나는 ICPC19를 -Ofastand -Os; MSVC -Ox-Os)

왜 이것이 사실인지 모르겠습니다 (실제로 std :: array 및 c-array의 정확히 동일한 동작을 기대합니다). 다른 최적화 전략이 사용되었을 수 있습니다.

약간의 추가 사항 : ICPC에 버그가있는 것 같습니다.

#pragma simd 

일부 상황에서 c-array를 사용할 때 벡터화를 위해 (c-array 코드가 잘못된 출력을 생성하고 std::array버전이 잘 작동 함).

불행히도, 꽤 복잡한 코드를 최적화하는 동안 그 문제를 발견했기 때문에 아직 최소한의 작업 예제가 없습니다.

C-array / std::array및에 대해 오해하지 않았다고 확신하는 경우 인텔에 버그 보고서를 제출할 것 #pragma simd입니다.


1
컴파일러 버그로 간주 될 수 있습니까?
OznOg

8

std::array원시 배열에는없는 반면 값 의미는 있습니다. 즉 std::array, 원시 값처럼 복사 하고 처리 할 수 있습니다 . 함수 인수로 값 또는 참조로받을 수 있으며 값으로 반환 할 수 있습니다.

를 복사하지 않으면 std::array원시 배열과 성능 차이가 없습니다. 복사본을 만들어야 std::array하는 경우 올바른 작업을 수행하고 동일한 성능을 제공해야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.