가변 길이 배열이 C ++ 표준의 일부가 아닌 이유는 무엇입니까?


326

지난 몇 년 동안 C를 많이 사용하지 않았습니다. 오늘 이 질문을 읽으면 익숙하지 않은 C 구문을 발견했습니다.

분명히 C99 에서는 다음 구문이 유효합니다.

void foo(int n) {
    int values[n]; //Declare a variable length array
}

이것은 매우 유용한 기능인 것 같습니다. C ++ 표준에 추가하는 것에 대한 토론이 있었습니까? 그렇다면 왜 생략 되었습니까?

몇 가지 잠재적 인 이유 :

  • 컴파일러 공급 업체가 구현하기에 적합
  • 표준의 다른 부분과 호환되지 않습니다
  • 다른 C ++ 구문으로 기능을 에뮬레이션 할 수 있습니다.

C ++ 표준에 따르면 배열 크기는 상수 식 (8.3.4.1)이어야합니다.

물론 장난감 예제에서는을 사용할 수 있다는 것을 알고 std::vector<int> values(m);있지만 스택이 아닌 힙에서 메모리를 할당합니다. 그리고 다음과 같은 다차원 배열을 원한다면 :

void foo(int x, int y, int z) {
    int values[x][y][z]; // Declare a variable length array
}

vector버전은 꽤 서투른된다 :

void foo(int x, int y, int z) {
    vector< vector< vector<int> > > values( /* Really painful expression here. */);
}

슬라이스, 행 및 열도 메모리 전체에 분산 될 수 있습니다.

토론을 보면 comp.std.c++이 질문이 논쟁의 양쪽에 매우 무거운 이름으로 꽤 논란의 여지가 있음이 분명합니다. a std::vector가 항상 더 나은 솔루션 이라는 것은 확실하지 않습니다 .


3
호기심 때문에 스택에 할당해야하는 이유는 무엇입니까? 힙 할당 성능 문제가 두렵습니까?
Dimitri C.

32
@Dimitri 실제로는 아니지만 스택 할당이 힙 할당보다 빠르다는 것을 부정하지는 않습니다. 그리고 어떤 경우에는 이것이 중요 할 수 있습니다.
Andreas Brinck '12

11
가변 길이 배열의 주요 장점은 모든 데이터가 서로 가깝기 때문에이 배열을 반복 할 때 서로 옆에 바이트를 읽고 씁니다. 데이터는 캐시로 페치되며 CPU는 바이트를 페치하여 메모리로 /로부터 전송하지 않고도 데이터를 처리 할 수 ​​있습니다.
Calmarius

4
가변 길이 배열을 사용하여 전 처리기 상수를 정적 const 변수로 바꿀 수도 있습니다. 또한 C에는 VLA에 대한 다른 옵션이 없으며 때로는 휴대용 C / C ++ 코드 (두 컴파일러와 호환 가능)를 작성해야합니다.
Yury

2
옆으로, clang ++은 VLA를 허용하는 것으로 보입니다.
user3426763

답변:


204

최근 유즈넷에서 쫓겨 이에 대한 토론이 있었다 : 왜 C + +0 없음 블라스 .

일반적으로 사용 가능한 공간이 거의없는 스택에 잠재적으로 큰 배열을 생성하는 것이 좋지 않다는 데 동의하는 사람들에 동의합니다. 인수는 크기를 미리 알고 있다면 정적 배열을 사용할 수 있다는 것입니다. 미리 크기를 모르면 안전하지 않은 코드를 작성합니다.

C99 VLA는 공간을 낭비하거나 사용하지 않는 요소에 대해 생성자를 호출하지 않고도 작은 배열을 만들 수 있다는 작은 이점을 제공 할 수 있지만 유형 시스템에 약간의 변경이 발생할 수 있습니다 (런타임 값에 따라 유형을 지정할 수 있어야 함). new연산자 유형 지정자를 제외하고 현재 C ++에는 아직 존재하지 않지만 런타임 처리가 new연산자 의 범위를 벗어나지 않도록 특별히 처리 됩니다.

을 사용할 수는 std::vector있지만 동적 메모리를 사용하고 자체 스택 할당기를 사용하는 것은 쉽지 않습니다 (정렬도 문제입니다). 벡터는 크기 조정이 가능한 컨테이너 인 반면 VLA는 고정 크기이므로 동일한 문제를 해결하지 못합니다. C ++ 동적 배열 제안은 VLA 기반 언어에 대한 대안으로, 라이브러리 기반 솔루션을 소개하기위한 것입니다. 그러나 내가 아는 한 C ++ 0x의 일부는 아닙니다.


22
+1하고 수락했습니다. 그러나 한 의견은 스택 오버플로를 일으킬 수있는 다른 많은 방법이 있기 때문에 안전 인수가 약간 약하다고 생각합니다. 안전 인수는 재귀를 사용해서는 안되며 힙에서 모든 객체를 할당 해야하는 위치를 지원하는 데 사용할 수 있습니다 .
Andreas Brinck 2009

17
따라서 스택 오버플로를 발생시키는 다른 방법이 있기 때문에 더 많은 것을 권장 할 수 있습니까?
jalf December

3
@Andreas는 약점에 동의했습니다. 그러나 재귀의 경우 스택이 소모 될 때까지 많은 호출이 필요하며, 가능하다면 사람들은 반복을 사용합니다. 그러나 유즈넷 스레드의 일부 사람들이 말하듯이 이것은 때로는 VLA에 대한 논쟁이 아닙니다. 때로는 상한을 확실히 알 수 있기 때문입니다. 그러나 이러한 경우에, 어쨌든 많은 공간을 낭비하지 것이기 때문에 내가 정적 배열이 동일하게 충분히 할 수 있습니다 무엇을보고에서 (이 경우 , 당신은 실제로 스택 영역이 충분히 큰 다시 여부를 문의 할 것).
Johannes Schaub-litb

10
또한 그 스레드에서 Matt Austern의 답변을 살펴보십시오. V ++의 언어 사양은 C ++에서 더 엄격한 유형 일치로 인해 C ++에 대해 훨씬 더 복잡 할 것입니다 (예 : C는 C ++에서 T(*)[]a를 T(*)[N]-로 지정할 수 있음). "유형 호환성"에 대해 알지 못함-정확히 일치해야 함), 유형 매개 변수, 예외, 소멸자 및 항목. VLA의 이점이 실제로 모든 일에 도움이 될지 확실하지 않습니다. 그러나 실제 생활에서 VLA를 사용한 적이 없으므로 적절한 사용 사례를 모릅니다.
Johannes Schaub-litb

1
@AHelps : 아마도 최선의 방법은 다소 동작 vector하지만 고정 된 LIFO 사용 패턴이 필요하고 스레드 당 정적 할당 CPU를 하나 이상 유지 하는 유형 일 것입니다.이 스레드는 일반적으로 스레드가 가지고있는 가장 큰 총 할당에 따라 크기가 조정됩니다 사용되었지만 명시 적으로 다듬을 수 있습니다. 일반적인 "할당"은 일반적인 경우 포인터 복사, 포인터에서 포인터 빼기, 정수 비교 및 ​​포인터 추가 만 필요합니다. 할당 해제는 단순히 포인터 사본이 필요합니다. VLA보다 느리지 않습니다.
supercat

216

(배경 : C 및 C ++ 컴파일러 구현 경험이 있습니다.)

C99의 가변 길이 배열은 기본적으로 잘못된 단계였습니다. VLA를 지원하기 위해 C99는 상식적으로 다음과 같은 양보를해야했습니다.

  • sizeof x더 이상 항상 컴파일 타임 상수는 아닙니다. 컴파일러는 때때로 sizeof런타임에 -expression 을 평가하기위한 코드를 생성해야합니다 .

  • 2 차원 VLA ( int A[x][y])를 허용 하려면 2D VLA를 매개 변수로 사용하는 함수를 선언하는 새로운 구문이 필요했습니다 void foo(int n, int A[][*]).

  • 덜 중요한 것은 C ++ 세계 있지만 받기를 갈망 VLA 수단 선언, 임베디드 시스템 프로그래머 C의 타겟 고객을위한 매우 중요한에서 임의의 큰 당신의 스택의 덩어리를. 이는 스택 오버플로 및 충돌을 보장 합니다. (언제든지 선언 할 때 int A[n], 2GB의 스택이 남을 것이라고 암시 적으로 주장합니다. 결국 " n여기에서 확실히 1000보다 작습니다 "를 알고 있다면을 선언하면 int A[1000]됩니다. 32 비트 정수 n를 대체하는 1000것은 입학 프로그램의 동작이 무엇인지 모릅니다.)

자 이제 C ++에 대해 이야기하도록하겠습니다. C ++에서, 우리는 "타입 시스템"과 "가치 시스템"사이에 C89와 같은 강력한 차이점이 있습니다. 예를 들면 다음과 같습니다.

template<typename T> struct S { ... };
int A[n];
S<decltype(A)> s;  // equivalently, S<int[n]> s;

n컴파일 타임 상수가 아닌 경우 (즉, A가변적으로 수정 된 유형 인 경우) 지구상의 유형은 S무엇입니까? 겠습니까 S의 유형은 또한 실행시에 결정된다?

이건 어때?

template<typename T> bool myfunc(T& t1, T& t2) { ... };
int A1[n1], A2[n2];
myfunc(A1, A2);

컴파일러는의 인스턴스화를위한 코드를 생성해야합니다 myfunc. 그 코드는 어떻게 생겼습니까? A1컴파일 타임 의 유형을 모르는 경우 어떻게 정적으로 코드를 생성 할 수 있습니까?

더 나쁜, 무엇을 런타임에 밝혀지면 그 n1 != n2, 그래서 !std::is_same<decltype(A1), decltype(A2)>()? 이 경우 템플릿 유형 공제가 실패하기 때문에에 대한 호출 myfunc 은 컴파일되지 않아야합니다! 런타임에 어떻게 그 동작을 에뮬레이트 할 수 있습니까?

기본적으로 C ++은 템플릿 코드 생성, 함수 평가 등과 같이 점점 더 많은 결정을 컴파일 타임 으로 추진하는 방향으로 나아가고 constexpr있습니다. 한편, C99는 전통적으로 컴파일 타임 결정 (예를 들어 sizeof)을 런타임 으로 추진하는 데 바빴습니다 . 이를 염두에두고 C99 스타일 VLA를 C ++에 통합 하려는 노력 을 기울이는 것이 합리적 일까요?

다른 모든 응답자가 이미 지적했듯이 C ++은 "필요한 RAM의 양을 전혀 모른다"라는 아이디어를 전달하고자 할 때 많은 힙 할당 메커니즘 ( std::unique_ptr<int[]> A = new int[n];또는 std::vector<int> A(n);명백한 메커니즘 )을 제공합니다. 그리고 C ++은 필요한 RAM의 양이 RAM의 양보다 큰 불가피한 상황을 처리하기위한 멋진 예외 처리 모델을 제공합니다. 그러나이 답변 C99 스타일 VLA가 C ++에 적합 하지 않은 이유와 C99에 적합 하지 않은 이유에 대한 좋은 아이디어를 제공하기를 바랍니다 . ;)


이 주제에 대한 자세한 내용은 Vjar에 대한 Bjarne Stroustrup의 2013 년 10 월 백서 인 N3810 "어레이 확장을위한 대안"을 참조하십시오 . Bjarne의 POV는 나와 다릅니다. N3810은 사물에 대한 좋은 C ++ ish 구문 을 찾고 C ++ 에서 raw arrays를 사용하지 않는 데 중점을 두는 반면 메타 프로그래밍 및 형식 시스템에 대한 의미에 더 중점을 두었습니다. 그가 메타 프로그래밍 / 유형 시스템의 함의를 풀거나 해결할 수 있거나 단순히 흥미롭지 않은 것으로 간주하는지 모르겠습니다.


이와 같은 여러 가지 요점을 다루는 좋은 블로그 게시물은 "가변 길이 배열의 합법적 사용" (Chris Wellons, 2019-10-27)입니다.


15
VLA가 잘못되었다는 데 동의합니다. alloca()C99 에서는 훨씬 더 광범위하게 구현되고 훨씬 더 유용한 표준을 표준화해야했습니다. VLA는 표준위원회가 다른 방식이 아닌 구현보다 앞서 나갈 때 발생합니다.
MadScientist

10
다양하게 수정 된 유형 시스템은 IMO를 추가 한 훌륭한 요소이며 상식을 위반하는 부분은 없습니다. (1) C 표준은 "컴파일 타임"과 "런타임"을 구별하지 않으므로 문제가되지 않습니다. (2) 이것은 *선택 사항입니다 int A[][n]. (3) 실제로 VLA를 선언하지 않고 타입 시스템을 사용할 수 있습니다. 예를 들어, 함수는 가변적으로 수정 된 유형의 배열을 받아 들일 수 있으며 차원이 다른 VLA가 아닌 2 차원 배열로 호출 할 수 있습니다. 그러나 게시물의 후반부에 유효한 포인트를 제시합니다.
MM

3
"VLA를 선언한다는 것은 스택의 임의의 덩어리를 꽉 채우는 것을 의미합니다. 이것은 스택 오버플로 및 충돌을 보장합니다. 스택 오버플로없이 2GB 미만의 스택으로 VLA 프로그램을 실행했습니다
Jeff

3
@ Jeff : n테스트 케이스에서 최대 값은 얼마 였고 스택의 크기는 얼마입니까? n적어도 스택 크기만큼 큰 값을 입력하는 것이 좋습니다 . (그리고 사용자가 n프로그램에서 값을 제어 할 수있는 방법이 없다면 n선언 int A[1000]이나 필요한 것이 무엇이든 선언에 최대한의 값을 전파하는 것이 좋습니다 . VLA는 필요하고 위험합니다. 최대 n컴파일 값이 작은 컴파일 타임 상수에 의해 제한되지 않는 경우)
Quuxplusone

2
이러한 내장 함수를 사용하여 alloca ()를 구현할 수 있기 때문에 alloca ()는 컴파일러 표준 함수로 모든 플랫폼에서 구현 될 수 있습니다. 컴파일러가 alloca ()의 첫 번째 인스턴스를 감지 할 수없고 코드에 포함 할 마크 및 릴리스 유형을 정렬 할 이유가 없으며, 컴파일러가 힙을 사용하여 alloca ()를 구현할 수있는 이유가 없습니다. 스택으로는 할 수 없습니다. hard / portable은 C 컴파일러 위에 alloca ()를 구현 하여 다양한 컴파일러와 운영 체제에서 작동합니다.
MadScientist

26

원하는 경우 런타임에 alloca ()를 사용하여 스택에 메모리를 할당 할 수 있습니다.

void foo (int n)
{
    int *values = (int *)alloca(sizeof(int) * n);
}

스택에 할당된다는 것은 스택이 풀릴 때 스택이 자동으로 해제됨을 의미합니다.

빠른 참고 사항 : alloca (3)에 대한 Mac OS X 매뉴얼 페이지에서 언급 한 바와 같이, "alloca () 함수는 기계 및 컴파일러에 따라 다르며 사용이 권장되지 않습니다." 알다시피


4
또한 alloca ()의 범위는 변수를 포함하는 코드 블록뿐만 아니라 전체 함수입니다. 따라서 루프 내부에서 사용하면 스택이 지속적으로 증가합니다. VLA에는이 문제가 없습니다.
sashoalm

3
그러나 엔 클로징 블록의 범위를 갖는 VLA는 전체 함수의 범위가있는 alloca ()보다 훨씬 덜 유용합니다. 고려할 사항 : if (!p) { p = alloca(strlen(foo)+1); strcpy(p, foo); } 블록 범위로 인해 VLA를 사용하여이를 수행 할 수 없습니다.
MadScientist

1
그것은 OP의 이유 질문에 대답하지 않습니다 . 또한 이것은 C유사한 솔루션이며 실제로는 아닙니다 C++.
Adrian W

13

내 자신의 작업에서 가변 길이 자동 배열 또는 alloca ()와 같은 것을 원할 때마다 메모리가 실제로 CPU 스택에 위치하고 있다는 것을 신경 쓰지 않았다는 것을 깨달았습니다. 일반 힙으로 느리게 트립되지 않은 일부 스택 할당 자 그래서 가변 크기의 버퍼를 푸시 / 팝 할 수있는 메모리를 소유 한 스레드 당 객체가 있습니다. 일부 플랫폼에서는 mmu를 통해 이것이 커질 수 있습니다. 다른 플랫폼은 크기가 고정되어 있습니다 (보통 mmu가 없으므로 고정 크기 CPU 스택과 함께 제공됨). 내가 작업하는 하나의 플랫폼 (휴대용 게임 콘솔)에는 어쨌든 빠른 메모리에 있기 때문에 귀중한 작은 CPU 스택이 있습니다.

가변 크기의 버퍼를 CPU 스택에 밀어 넣을 필요가 없다고 말하는 것은 아닙니다. 솔직히 말해서 이것이 표준이 아니라는 것을 알았을 때 놀랐습니다. 개념이 언어에 잘 맞는 것처럼 보입니다. 그래도 "가변 크기"와 "CPU 스택에 물리적으로 위치해야합니다"라는 요구 사항은 결코 합쳐지지 않았습니다. 속도에 관한 것이었기 때문에 필자가 직접 "데이터 버퍼에 대한 병렬 스택"을 만들었다.


12

힙 메모리 할당이 수행되는 작업과 비교하여 비용이 많이 드는 상황이 있습니다. 예를 들어 행렬 수학이 있습니다. 작은 행렬로 5 ~ 10 개의 요소를 사용하고 많은 산술을 수행하는 경우 malloc 오버 헤드가 실제로 중요합니다. 동시에 크기를 컴파일 시간을 일정하게 만드는 것은 매우 낭비적이고 유연하지 않은 것처럼 보입니다.

C ++ 자체가 안전하지 않다고 생각하여 "안전하지 않은 기능을 더 추가하지 마십시오"라는 주장은 그다지 강력하지 않습니다. 반면에 C ++는 런타임에 가장 효율적인 프로그래밍 언어 기능이므로 항상 유용합니다. 성능이 중요한 프로그램을 작성하는 사람들은 C ++을 많이 사용하므로 가능한 한 많은 성능이 필요합니다. 힙에서 스택으로 물건을 옮기는 것이 그러한 가능성 중 하나입니다. 힙 블록 수를 줄이는 것도 또 다른 방법입니다. VLA를 객체 멤버로 허용하면이를 달성 할 수 있습니다. 나는 그런 제안을하고 있습니다. 물론 구현하기는 약간 복잡하지만 상당히 가능해 보입니다.


12

C ++ 14에서 사용할 수있는 것 같습니다 :

https://en.wikipedia.org/wiki/C%2B%2B14#Runtime-sized_one_dimensional_arrays

업데이트 : C ++ 14로 만들지 않았습니다.


흥미 롭군 Herb Sutter는 여기에서 Dynamic Arrays에 대해 설명합니다 : isocpp.org/blog/2013/04/trip-report-iso-c-spring-2013-meeting (wikipedia 정보에 대한 참조입니다)
Default

1
2014년 1월 18일에 위키 백과에 78.86.152.103을 썼다 "런타임 배열 및 DynArray를 배열 확장 기술 사양에 이동 된 크기" en.wikipedia.org/w/...
strager

10
Wikipedia는 규범적인 참조가 아닙니다 :)이 제안은 C ++ 14로 만들지 않았습니다.
MM

2
@ViktorSehr :이 wrt C ++ 17의 상태는 어떻습니까?
einpoklum

@einpoklum 모르겠습니다, boost :: container :: static_vector를 사용하십시오
Viktor Sehr

7

이것은 C ++ / 1x에 포함될 것으로 간주 되었지만 삭제되었습니다 (이것은 내가 이전에 말한 것에 대한 수정입니다).

어쨌든 우리는 이미이 std::vector역할을 수행 해야 하기 때문에 C ++에서는 유용하지 않습니다 .


42
아니요, std :: vector는 스택에 데이터를 할당하지 않습니다. :)
Kos

7
"스택"은 구현 세부 사항입니다. 컴파일러는 객체 수명에 대한 보장이 충족되는 한 어디서나 메모리를 할당 할 수 있습니다.
MM

1
@ MM : 충분히 공평하지만 실제로는 std::vector대신 대신 사용할 수 없습니다 alloca().
einpoklum 2016 년

@einpoklum 프로그램에 대한 올바른 출력을 얻는 측면에서 가능합니다. 성능은 구현 품질 문제입니다
MM

1
@MM 구현 품질은 이식성이 없습니다. 퍼포먼스가 필요하지 않다면 우선 C ++을 사용하지 않아도됩니다.
pal

3

이를 위해 std :: vector를 사용하십시오. 예를 들면 다음과 같습니다.

std::vector<int> values;
values.resize(n);

메모리는 힙에 할당되지만 작은 성능 저하 만 보유합니다. 또한, 크기가 다소 제한되어 있으므로 스택에 큰 데이터 블록을 할당하지 않는 것이 좋습니다.


4
가변 길이 배열의 주요 응용 프로그램은 임의의 다항식의 평가입니다. 이 경우 "작은 성능 단점"은 "일반적인 경우 코드가 5 배 느리게 실행됩니다"를 의미합니다. 작지 않습니다.
AHelps

1
왜 간단하게 사용하지 std::vector<int> values(n);않습니까? resize시공 후 사용 하면 움직일 수없는 유형이 금지됩니다.
LF

1

C99는 VLA를 허용합니다. 그리고 VLA를 선언하는 방법에 대한 제한이 있습니다. 자세한 내용은 표준 6.7.5.2를 참조하십시오. C ++은 VLA를 허용하지 않습니다. 그러나 g ++은 허용합니다.


가리키는 표준 단락에 대한 링크를 제공 할 수 있습니까?
Vincent

0

이와 같은 배열은 C99의 일부이지만 표준 C ++의 일부는 아닙니다. 다른 사람들이 말했듯이 벡터는 항상 훨씬 나은 솔루션이므로 가변 크기 배열이 C ++ standatrd (또는 제안 된 C ++ 0x 표준)에없는 이유 일 수 있습니다.

BTW, C ++ 표준이 "이유"인 방식에 대한 질문에 대해서는 검토 된 Usenet 뉴스 그룹 comp.std.c ++ 가 있습니다.


6
-1 벡터가 항상 좋은 것은 아닙니다. 종종 그렇습니다. 항상 요 작은 배열 만 필요하고 힙 공간이 느린 플랫폼에 있고 라이브러리의 벡터 구현에서 힙 공간을 사용하는 경우이 기능이 있으면 더 좋습니다.
Patrick M

-1

컴파일 타임에 값을 알고 있으면 다음을 수행 할 수 있습니다.

template <int X>
void foo(void)
{
   int values[X];

}

편집 : 할당자는 템플릿 매개 변수이므로 스택 할당 자 (alloca)를 사용하는 벡터를 만들 수 있습니다.


18
컴파일 타임에 값을 알고 있다면 템플릿이 전혀 필요하지 않습니다. 템플릿이 아닌 함수에서 직접 X를 사용하십시오.
Rob Kennedy

3
때때로 호출자는 컴파일 타임에 알지만 호출자는 알지 못합니다. 이것이 템플릿에 적합한 것입니다. 물론 일반적인 경우 런타임까지 X를 아는 사람은 없습니다.
Qwertie

STL 할당 자에서 alloca를 사용할 수 없습니다. alloca에서 할당 된 메모리는 스택 프레임이 파괴 될 때 해제됩니다. 즉, 메모리를 할당해야하는 메서드가 반환됩니다.
Oliver

-5

실제로 나를 위해 일한 해결책이 있습니다. 여러 번 실행 해야하는 루틴에서 조각화로 인해 메모리를 할당하고 싶지 않았습니다. 답은 매우 위험하므로 위험 부담으로 사용하되 스택의 공간을 확보하기 위해 어셈블리를 활용하십시오. 아래 예제는 문자 배열을 사용합니다 (확실히 다른 크기의 변수에는 더 많은 메모리가 필요합니다).

void varTest(int iSz)
{
    char *varArray;
    __asm {
        sub esp, iSz       // Create space on the stack for the variable array here
        mov varArray, esp  // save the end of it to our pointer
    }

    // Use the array called varArray here...  

    __asm {
        add esp, iSz       // Variable array is no longer accessible after this point
    } 
}

여기에 몇 가지 위험이 있지만 몇 가지를 설명하겠습니다. 1. 변수 크기를 절반으로 변경하면 스택 위치가 종료됩니다. 2. 배열 경계를 초과하면 다른 변수와 가능한 코드가 손상됩니다. 이것은 64 비트에서는 작동하지 않습니다. 빌드 ... 그것에 대해 다른 어셈블리가 필요합니다 (그러나 매크로는 그 문제를 해결할 수 있습니다). 4. 컴파일러에 따라 다릅니다 (컴파일러 간 이동에 문제가있을 수 있음). 나는 시도하지 않았으므로 나는 정말로 모른다.


... 이걸 직접 굴리려면 RAII 수업을 사용 하시겠습니까?
einpoklum

boost :: container :: static_vector를 사용할 수 있습니다.
Viktor Sehr

MSVC보다 원시 어셈블리가 더 많은 다른 컴파일러에 해당하는 기능이 없습니다. VC는 esp변경된 것을 이해하고 스택에 대한 액세스를 조정하지만 GCC에서는 최소한 최적화를 사용하는 경우 -fomit-frame-pointer, 특히 최적화를 사용하는 경우이를 완전히 중단합니다 .
Ruslan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.