Jeśli chcę zbudować bardzo prostą tablicę, taką jak
int myArray[3] = {1,2,3};
Powinienem użyć std::array
zamiast tego?
std::array<int, 3> a = {{1, 2, 3}};
Jakie są zalety używania std :: array nad zwykłymi? Czy jest bardziej wydajny? Po prostu łatwiejsze w obsłudze do kopiowania / dostępu?
for (auto i = ++std::begin(myArray); . . .
może nawet się nie kompilować (wydaje się, że elementy tymczasowe typu podstawowego nie są zmienne, przynajmniej nie z clang 6)struct Direction { int32_t dw; int32_t dh; };
istatic const Direction DIRECTIONS[DIRECTIONS_COUNT] { { -1, 1}, {0,1}, {1,1} , { 1, 0 }, {1,-1}, {0,-1} , {-1,-1}, {-1,0} };
kompiluje. Ale jeśli zmienisz nastd::array<Direction,DIRECTIONS_COUNT>
z tą samą listą inicjalizatorów, nagle pojawi się błąd „zbyt wiele inicjatorów”. (Społeczność VS 2019 z językiem = C ++ 17)std::array
inicjalizacji?Odpowiedzi:
Ma przyjazną semantykę wartości, dzięki czemu może być przekazywany lub zwracany z funkcji przez wartość. Jego interfejs ułatwia znalezienie rozmiaru i korzystanie z algorytmów opartych na iteratorach w stylu STL.
Powinien być dokładnie taki sam. Z definicji jest to prosta agregacja zawierająca tablicę jako jedyny element członkowski.
Tak.
źródło
A
std::array
to bardzo cienkie opakowanie wokół tablicy w stylu C, zasadniczo zdefiniowane jakotemplate<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 };
Jest to agregat i pozwala na używanie go prawie jak podstawowego typu (tj. Można przekazać wartość, przypisać itp., Podczas gdy standardowej tablicy C nie można przypisać ani skopiować bezpośrednio do innej tablicy). Powinieneś rzucić okiem na jakąś standardową implementację (przeskocz do definicji ze swojego ulubionego IDE lub otwórz bezpośrednio
<array>
), jest to fragment standardowej biblioteki C ++, który jest dość łatwy do odczytania i zrozumienia.źródło
std::array
jest zaprojektowany jako opakowanie z zerowym narzutem dla tablic C, które nadaje mu „normalną” wartość, podobnie jak semantyka innych kontenerów C ++.Nie powinieneś zauważyć żadnej różnicy w wydajności środowiska uruchomieniowego, podczas gdy nadal możesz cieszyć się dodatkowymi funkcjami.
Używanie tablic stylów
std::array
zamiastint[]
tablic stylów jest dobrym pomysłem, jeśli masz pod ręką C ++ 11 lub boost.źródło
Sytuacja wydaje się być bardziej skomplikowana, ponieważ
std::array
nie zawsze tworzy identyczny kod asemblera w porównaniu z tablicą C, w zależności od konkretnej platformy.Przetestowałem tę konkretną sytuację na 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]; } }
GCC i Clang generują identyczny kod asemblera zarówno dla wersji C-array, jak i dla
std::array
wersji.Jednak MSVC i ICPC generują inny kod asemblera dla każdej wersji macierzy. (Testowałem ICPC19 z
-Ofast
i-Os
; MSVC-Ox
i-Os
)Nie mam pojęcia, dlaczego tak jest (rzeczywiście spodziewałbym się dokładnie identycznego zachowania std :: array i c-array). Może są stosowane różne strategie optymalizacji.
Jako mały dodatek: wygląda na to, że w ICPC jest błąd z
#pragma simd
do wektoryzacji podczas używania tablicy c w niektórych sytuacjach (kod c-array generuje nieprawidłowe dane wyjściowe;
std::array
wersja działa dobrze).Niestety nie mam jeszcze minimalnego przykładu roboczego na to, ponieważ odkryłem ten problem podczas optymalizacji dość skomplikowanego fragmentu kodu.
Prześlę raport o błędzie do firmy Intel, gdy będę pewien, że nie tylko źle zrozumiałem coś o C-array /
std::array
i#pragma simd
.źródło
std::array
ma semantykę wartości, podczas gdy surowe tablice nie. Oznacza to, że możesz go skopiowaćstd::array
i traktować jak wartość pierwotną. Możesz je otrzymać jako wartość lub odwołanie jako argumenty funkcji i możesz zwrócić je według wartości.Jeśli nigdy nie kopiujesz
std::array
, nie ma różnicy w wydajności niż surowa tablica. Jeśli musisz zrobić kopie,std::array
postąpisz właściwie i nadal powinieneś dawać taką samą wydajność.źródło