std::array
C 배열보다 훨씬 우수합니다. 레거시 코드와 상호 운용하려는 경우에도 std::array::data()
. 내가 구식 배열을 원하는 이유가 있습니까?
std::array
C 배열보다 훨씬 우수합니다. 레거시 코드와 상호 운용하려는 경우에도 std::array::data()
. 내가 구식 배열을 원하는 이유가 있습니까?
답변:
내가 놓친 것이 아니라면 (최근의 표준 변경 사항을 너무 가깝게 따르지 않았 음) 대부분의 C 스타일 배열 사용은 여전히 남아 있습니다. std::array
정적 초기화를 허용하지만 여전히 이니셜 라이저를 계산하지 않습니다. 그리고 이전에 C 스타일 배열의 유일한 실제 사용은 std::array
다음 행을 따라 정적으로 초기화 된 테이블에 대한 것이기 때문 입니다.
MyStruct const table[] =
{
{ something1, otherthing1 },
// ...
};
일반 begin
및 end
템플릿 함수 (C ++ 11에서 채택)를 사용하여 반복합니다. 컴파일러가 이니셜 라이저 수에서 결정하는 크기는 언급하지 않습니다.
편집 : 내가 잊은 또 다른 점 : 문자열 리터럴은 여전히 C 스타일 배열입니다. 즉 유형 char[]
. 나는 우리가 std::array
.
const char[]
아뇨 .. 솔직히 말 해서요 그리고 30 자입니다.
물론을 구현하려면 C 배열이 필요 std::array
하지만 이것이 실제로 사용자가 C 배열을 원하는 이유는 아닙니다. 또한, 아니, std::array
C 배열보다 확대됨에없는, 그리고 경계 - 검사 액세스를위한 옵션이 있습니다. 마지막으로 모든 C ++ 프로그램이 표준 라이브러리에 의존하는 것은 완전히 합리적입니다. 즉, 표준 라이브러리에 대한 액세스 권한이없는 경우 컴파일러는 표준 라이브러리를 따르지 않습니다. 질문은 "C ++"가 아니라 "C ++"로 태그가 지정되어 있으며, 부적절하다고 느꼈기 때문에 사양의 절반을 놓친 C ++가 아닌 것입니다.
std::array
독립형 C ++ 11 구현에서는 구현할 수없는 컴파일러에 대해 심각한 의구심을 가질 것 입니다.
다차원 배열을 사용하는 것이 C 배열보다 std::array
. 예를 들어
char c_arr[5][6][7];
반대로
std::array<std::array<std::array<char, 7>, 6>, 5> cpp_arr;
또한 C 배열의 자동 감쇠 속성으로 인해 c_arr[i]
위의 예에서 포인터로 감쇠하고 나머지 차원을 두 개의 추가 매개 변수로 전달하면됩니다. 내 요점은 c_arr
복사하는 데 비싸지 않다는 것 입니다. 그러나 cpp_arr[i]
복사하는 데 비용이 많이 듭니다.
array
차원을 잃지 않고 다차원 을 함수에 전달할 수 있습니다. 그리고 그것을 함수 템플릿에 전달하면 그 함수는 각 차원의 차원과 크기를 모두 추론하거나 둘 중 하나만 추론 할 수 있습니다. 이것은 주로 임의의 차원에서 작동하는 과학적 템플릿 라이브러리에 흥미로울 수 있습니다.
template <typename T, int M, int N> using array2d = std::array<std::array<T, N>, M>;
것은 이러한 문제를 해결해야합니다.
c_arr
는 복사하는 데 매우 비쌉니다! 그렇게하려면 코드를 직접 제공해야합니다. 감쇠되는 포인터는 복사본보다 참조에 더 가깝고 std::array
원하는 경우 참조를 전달하는 데 사용할 수 있습니다 .
std::size_t
대신 해야하지 int
않습니까? nitpicking 미안하지만 이것은 보편적으로 만들 것입니다.
size_t
, 원하는 경우 만들 수 있습니다 .하지만 40 억 개 이상의 행 또는 열이있는 배열이 필요한 시나리오가 많다는 것은 상상할 수 없습니다.
Sumant가 말했듯이 다차원 배열은 std::array
.
중첩되면 std::array
읽기가 매우 어려워지고 불필요하게 장황해질 수 있습니다.
예를 들면 :
std::array<std::array<int, 3>, 3> arr1;
에 비해
char c_arr[3][3];
또한, 참고 begin()
, end()
및 size()
모든 반환 의미 값을 때 둥지 std::array
.
이러한 이유로 고정 크기의 다차원 배열 컨테이너 array_2d
및 array_3d
. 그들은 유사합니다std::array
하지만 2 차원 및 3 차원의 다차원 배열에 사용됩니다. 내장 된 다차원 배열보다 안전하고 성능이 나쁘지 않습니다. 흔하지 않기 때문에 차원이 3보다 큰 다차원 배열에 대한 컨테이너를 포함하지 않았습니다. C ++ 0x에서는 임의의 차원 수를 지원하는 가변 템플릿 버전을 만들 수 있습니다.
2 차원 변형의 예 :
//Create an array 3 x 5 (Notice the extra pair of braces)
fsma::array_2d <double, 3, 5> my2darr = {{
{ 32.19, 47.29, 31.99, 19.11, 11.19},
{ 11.29, 22.49, 33.47, 17.29, 5.01 },
{ 41.97, 22.09, 9.76, 22.55, 6.22 }
}};
전체 문서는 여기에서 볼 수 있습니다.
http://fsma.googlecode.com/files/fsma.html
여기에서 라이브러리를 다운로드 할 수 있습니다.
arr[x][y]
인지 알 수 없습니다 arr
. 구현을위한 모든 것은 필요에 따라 합법적입니다. 그리고 아마도 다차원 배열에 대한 대부분의 실제 사용 사례에서는 런타임에 크기를 결정해야합니다.
C ++에서 사용할 수있는 C 스타일 배열은 실제로 실제 C 배열보다 훨씬 덜 다재다능합니다. 차이점은 C에서는 배열 유형이 런타임 크기를 가질 수 있다는 것 입니다. 다음은 유효한 C 코드이지만 C ++ C 스타일 배열이나 C ++ array<>
유형 으로 표현할 수 없습니다 .
void foo(int bar) {
double tempArray[bar];
//Do something with the bar elements in tempArray.
}
C ++에서는 힙에 임시 배열을 할당해야합니다.
void foo(int bar) {
double* tempArray = new double[bar];
//Do something with the bar elements behind tempArray.
delete[] tempArray;
}
이는 컴파일 타임에 알려지지 std::array<>
않았기 때문에 으로 달성 할 수 없습니다 . bar
C ++ 또는의 C 스타일 배열을 사용해야합니다 std::vector<>
.
첫 번째 예는 비교적 용이 (요구되는 이나마 ++ C로 표현 될 수 있지만 new[]
하고 delete[]
, 다음은 C ++없이 달성 될 수있다) std::vector<>
:
void smoothImage(int width, int height, int (*pixels)[width]) {
int (*copy)[width] = malloc(height*sizeof(*copy));
memcpy(copy, pixels, height*sizeof(*copy));
for(y = height; y--; ) {
for(x = width; x--; ) {
pixels[y][x] = //compute smoothed value based on data around copy[y][x]
}
}
free(copy);
}
요점은 라인 배열에 대한 포인터가 int (*)[width]
C ++에서 런타임 너비를 사용할 수 없다는 것입니다. 이로 인해 C ++에서 C에서보다 이미지 조작 코드가 훨씬 더 복잡해집니다. 이미지 조작 예제의 일반적인 C ++ 구현은 다음과 같습니다.
void smoothImage(int width, int height, int* pixels) {
int* copy = new int[height*width];
memcpy(copy, pixels, height*width*sizeof(*copy));
for(y = height; y--; ) {
for(x = width; x--; ) {
pixels[y*width + x] = //compute smoothed value based on data around copy[y*width + x]
}
}
delete[] copy;
}
이 코드는 위의 C 코드와 정확히 동일한 계산을 수행하지만 인덱스가 사용되는 모든 곳에서 수동으로 인덱스 계산을 수행해야합니다 . 2D의 경우 여전히 가능합니다 (지수 계산을 잘못 할 수있는 많은 기회가 있음에도 불구하고). 하지만 3D 케이스에서는 정말 불쾌 해집니다.
저는 C ++로 코드를 작성하는 것을 좋아합니다. 하지만 다차원 데이터를 조작해야 할 때마다 코드의 해당 부분을 C로 옮겨야하는지 스스로에게 물어 봅니다.
gcc
예 :)을 구현하는 컴파일러가 있습니다. C11은 꽤 흥미로운 것들을 선택적으로 만들었고, 그들이 그 기능을 금지하기를 원하기 때문이라고 생각하지 않습니다. 나는 그것을 완전히 표준 호환 컴파일러를 작성하기 위해 레벨을 낮추고 싶다는 신호로 보는 경향이 있습니다 .VLA는 구현하기가 매우 어려운 짐승이며 많은 코드가 없이도 할 수 있으므로 새로운 컴파일러가 새로운 컴파일러에 적합합니다. VLA를 즉시 구현할 필요가 없습니다.
std::array
느리지 않을 수 있습니다 . 그러나 간단한 저장소를 사용하여 벤치마킹을 수행하고 std :: array에서 읽었습니다. 아래 벤치 마크 결과를 참조하십시오 (W8.1, VS2013 업데이트 4).
ARR_SIZE: 100 * 1000
Avrg = Tick / ARR_SIZE;
test_arr_without_init
==>VMem: 5.15Mb
==>PMem: 8.94Mb
==>Tick: 3132
==>Avrg: 0.03132
test_arr_with_init_array_at
==>VMem: 5.16Mb
==>PMem: 8.98Mb
==>Tick: 925
==>Avrg: 0.00925
test_arr_with_array_at
==>VMem: 5.16Mb
==>PMem: 8.97Mb
==>Tick: 769
==>Avrg: 0.00769
test_c_arr_without_init
==>VMem: 5.16Mb
==>PMem: 8.94Mb
==>Tick: 358
==>Avrg: 0.00358
test_c_arr_with_init
==>VMem: 5.16Mb
==>PMem: 8.94Mb
==>Tick: 305
==>Avrg: 0.00305
네거티브 마크에 따르면 내가 사용한 코드는 pastebin ( link )에 있습니다.
벤치 마크 클래스 코드는 여기에 있습니다 .
벤치마킹에 대해 잘 모르겠습니다 ... 내 코드에 결함이있을 수 있습니다.
long test_arr_without_init() { return ARR_SIZE; }
void test_arr_without_init() {}
지금 으로 바꿀 수 있습니다 . 측정하려는 코드가 측정하려는 코드인지 확인하기 위해 작업을 진행해야합니다.
std::array
std::array
C 어레이보다 성능이 떨어지는 방법 을 알려주십시오 .
at()
, 그것은에없는 operator[]
것처럼 std::vector
. 성능 저 하나 코드 부풀림이 없으며 std::array
컴파일러는 이러한 종류의 최적화를 위해 설계되었습니다. 물론 체크 된 기능의 추가는 훌륭한 디버그 도구이자 큰 장점입니다. @Lou Franco : 모든 C ++ 코드는 표준 라이브러리에 의존 할 수 있습니다. @Earlz : STL을 사용할 수 없다면 C ++가 아닙니다. 그게 끝입니다.
std::array
동등한 C 배열 사용보다 더 많이 사용하려면 엉뚱한 컴파일러 가 있어야합니다.