new를 사용하여 C ++에서 2d 배열을 선언하려면 어떻게합니까?


527

new를 사용하여 2d 배열을 어떻게 선언합니까?

"일반"배열의 경우 다음과 같습니다.

int* ary = new int[Size]

그러나

int** ary = new int[sizeY][sizeX]

a) 작동하지 않거나 컴파일되지 않으며 b) 다음을 수행하지 않습니다.

int ary[sizeY][sizeX] 

그렇습니다.


60
sizeX가 일정한 경우에만 작동합니다 : int (* ary) [sizeX] = new int [sizeY] [sizeX]; int [sizeY] [sizeX]를 만드는 올바른 방법이며 모든 메모리가 인접한 곳입니다. (아마도 sizeX가 일정하지 않기 때문에 이것이 대답 할 가치가 없다고 생각합니다.
Johannes Schaub-litb

23
나는 아래의 12 가지 답변이 모두 틀렸다는 것을 믿을 수는 없지만 질문에 대답하지는 않지만 여전히 답이 있습니다. Johanes Shaub의 위의 의견은이 질문에 대한 유일한 정답 입니다. 2D 배열과 배열에 대한 포인터 배열은 완전히 분리 된 것입니다.
Bregalad

6
@ JohannesSchaub-litb : 100 % 정확하지 않습니다. 확실히 그 경우에는 작동하지만 모든 치수가 다른 곳에서 작동하도록하는 방법이 있습니다. stackoverflow.com/a/29375830/103167
Ben Voigt

답변:


749

동적 2D 배열은 기본적으로 배열에 대한 포인터 배열 입니다. 다음과 같이 루프를 사용하여 초기화 할 수 있습니다.

int** a = new int*[rowCount];
for(int i = 0; i < rowCount; ++i)
    a[i] = new int[colCount];

상기는, 위해 colCount= 5rowCount = 4다음을 생성 할 것입니다 :

여기에 이미지 설명을 입력하십시오


143
할당 된 모든 new것은 힙에 생성되며으로 할당 해제해야합니다.이를 delete염두에두고 누출을 방지하기 위해 힙을 다 사용한 후에는이 메모리를 힙에서 삭제하십시오.
Kekoa 2016 년

83
또한 이것은 포인터의 배열입니다. 배열이 아닙니다. 포인터는 차례로 배열을 가리 킵니다. 많은 튜토리얼도 잘못되기 때문에 용어를 실제로 수정하는 것이 중요합니다. 배열의 배열이 하나하지 않은, 연속적인 것
요하네스 SCHAUB - litb

4
예, T [] [N]은 "T의 배열 [N] 배열"이라고하며 불완전한 유형이지만 T [] []는 유효하지 않은 유형입니다 (마지막 치수를 제외한 모든 크기는 알려진 크기를 가져야 함) ). T [N] [M]은 "T의 배열 [M]의 배열 [N]"이고, T [sizeX]는 "T의 배열 [sizeX]"입니다. 여기서 T는 int에 대한 포인터입니다. 동적으로 2 차원 배열을 생성하는 방법은 다음과 같습니다 : new int [X] [Y]. 할당 유형 int [X] [Y]의 배열을 작성합니다. C ++의 일반적인 유형 시스템에는 컴파일 타임에 알려지지 않은 크기의 배열 차원이 없기 때문에 이것은 "할당 된 유형"이라고 부릅니다.
Johannes Schaub-litb

34
세상에, 이것은 완전한 쓰레기입니다. 이것은 완전히 잘못되었습니다. 이것은 2D 배열이 아닙니다. "동적 2D 배열은 기본적으로 배열에 대한 포인터 배열입니다." – 누우, FFS! T (*ptr)[M] = new T[N][M];올바른 해결책입니다… 포인터 배열의 수는 배열 배열과 같지 않습니다…
상자성 크로와상

7
@TheParamagneticCroissant 2D 배열이 아니라고 주장 할 수 있습니다. 사실입니다. 2D 배열처럼 색인을 생성 할 수 있지만 2D 배열은 아닙니다. 메모리 레이아웃은 실제로 그림에 묘사되어 있습니다. 그 진술의 문제는 M이 일정하지 않으면 작동하지 않는다는 것입니다.
Mehrdad Afshari 2016 년

300
int** ary = new int[sizeY][sizeX]

해야한다:

int **ary = new int*[sizeY];
for(int i = 0; i < sizeY; ++i) {
    ary[i] = new int[sizeX];
}

정리는 다음과 같습니다.

for(int i = 0; i < sizeY; ++i) {
    delete [] ary[i];
}
delete [] ary;

편집 : Dietrich Epp가 의견에서 지적했듯이 이것은 정확히 가벼운 해결책이 아닙니다. 다른 방법은 하나의 큰 메모리 블록을 사용하는 것입니다.

int *ary = new int[sizeX*sizeY];

// ary[i][j] is then rewritten as
ary[i*sizeY+j]

56
필요한 것보다 약간 무겁고 필요한 것보다 많은 블록을 할당합니다. 다차원 배열은 하나의 메모리 블록 만 필요하며 행당 하나의 블록이 필요하지 않습니다. 하나의 블록 만 할당하면 정리가 더 간단 해집니다.
Dietrich Epp

11
@Kevin : 하나의 연속 블록 만 할당하는 것이 좋습니다 (할당 자에 대한 영향, 더 나은 지역성 등). 그러나 깨끗한 첨자를 희생 할 필요는 없습니다. 참조 stackoverflow.com/a/29375830/103167
벤 보이트

9
그렇지 i*sizeX+j않습니까? 올바르게 호출하면 주요 행 순서로 row * numColumns + col이어야합니다.
arao6

2
흠, 좋은 생각, 사실 그것은 표현의 문제 일뿐입니다. 나머지는 원근법입니다. 영리한
미로로도 조프

1
@Borna : 일반적으로 단일 2D 배열을 사용하는 것이 배열 배열보다 빠릅니다. 두 개의 포인터를 따라 가면 파이프 라인이 정지 될 수 있습니다. 항상 그렇듯이 액세스 패턴에 따라 다릅니다.
Dietrich Epp

211

이 인기있는 답변 이 원하는 색인 ​​구문을 제공 하지만 공간과 시간 모두에서 크고 느린 비효율적입니다. 더 좋은 방법이 있습니다.

그 대답이 크고 느린 이유

제안 된 솔루션은 동적 포인터 배열을 만든 다음 각 포인터를 독립적 인 동적 배열로 초기화하는 것입니다. 이 방법 의 장점 은 익숙한 인덱싱 구문을 제공하므로 x, y 위치에서 행렬 값을 찾으려면 다음과 같이 말합니다.

int val = matrix[ x ][ y ];

이것은 matrix [x]가 배열에 대한 포인터를 반환하고 [y]로 색인되기 때문에 작동합니다. 세분화 :

int* row = matrix[ x ];
int  val = row[ y ];

편리 해요? 우리는 [x] [y] 구문을 좋아합니다.

그러나이 솔루션은 큰 단점 이 있는데, 이는 지방과 느리다는 것입니다.

왜?

그것이 뚱뚱하고 느리다는 이유는 실제로 동일합니다. 행렬의 각 "행"은 별도로 할당 된 동적 배열입니다. 힙 할당은 시간과 공간 모두에서 비싸다. 할당자는 할당하는 데 시간이 걸리며 때로는 O (n) 알고리즘을 실행하여 할당합니다. 할당자는 예약 및 정렬을 위해 여분의 바이트로 각 행 배열을 "패드"합니다. 그 여분의 공간은 ... 음 ... 추가 공간입니다. 할당 해제는 또한 매트릭스를 할당 해제 할 때 추가 시간이 걸리며 각 개별 행 할당을 힘들게 해제합니다. 생각 만해도 땀을 흘린다.

속도가 느린 또 다른 이유가 있습니다. 이러한 개별 할당은 메모리의 불연속 부분에있는 경향이 있습니다. 한 행은 주소 1,000에, 다른 행은 주소 100,000에있을 수 있습니다. 이것은 매트릭스를 통과 할 때 거친 사람처럼 기억을 뛰어 넘는다는 것을 의미합니다. 이로 인해 캐시 누락이 발생하여 처리 시간이 크게 느려집니다.

따라서 귀여운 [x] [y] 색인 구문이 있어야한다면 해당 솔루션을 사용하십시오. 신속 함과 소량을 원한다면 (그리고 C ++로 작업하는 이유는 무엇입니까?) 다른 솔루션이 필요합니다.

다른 해결책

더 나은 솔루션은 전체 행렬을 단일 동적 배열로 할당 한 다음 자신의 (약간) 영리한 인덱싱 수학을 사용하여 셀에 액세스하는 것입니다. 인덱싱 수학은 매우 영리합니다. 아아, 그것은 영리하지 않다 : 그것은 분명하다.

class Matrix
{
    ...
    size_t index( int x, int y ) const { return x + m_width * y; }
};

index()함수 (내가 상상하고있는 함수는 m_width행렬 을 알아야하기 때문에 클래스의 멤버입니다)를 감안할 때 행렬 배열 내의 셀에 액세스 할 수 있습니다. 행렬 배열은 다음과 같이 할당됩니다.

array = new int[ width * height ];

따라서 느리고 뚱뚱한 해결책에서 이것과 동등합니다.

array[ x ][ y ]

... 이것은 빠르고 작은 솔루션입니다 :

array[ index( x, y )]

슬프다 그러나 당신은 그것에 익숙해 질 것입니다. 그리고 당신의 CPU는 당신을 감사합니다.


5
@Noein, 나는 특정 솔루션을 처방하지 않고 솔루션을 스케치했습니다. 더 자세한 내용은 다음과 같습니다. class Matrix { int* array; int m_width; public: Matrix( int w, int h ) : m_width( w ), array( new int[ w * h ] ) {} ~Matrix() { delete[] array; } int at( int x, int y ) const { return array[ index( x, y ) ]; } protected: int index( int x, int y ) const { return x + m_width * y; } };해당 코드를 수정하면 의미가있을 수 있으며 위의 답변을 밝힐 수 있습니다.
OldPeculier

4
나는이 솔루션을 많이 좋아합니다 .3 차원 배열에도 적용 가능합니까? 나는 이런 식으로 생각하고 있습니다 : (x + m_width * y) + (m_width * m_height * z)
Ulrar

3
이 솔루션주요 문제점 은 모든 인덱스에 대해 추가 계산 이 있다는 것입니다 . 그것은 당신이 함수에 인덱스 계산을 넣으면 더 악화 될 추가 오버 헤드를 추가합니다. 최소한 매크로인라인 함수 를 사용하여 오버 헤드를 줄이십시오. C ++의 매크로 예제 : #define ROW_COL_TO_INDEX(row, col, num_cols) (row*num_cols + col)다음과 같이 사용할 수 있습니다 int COLS = 4; A[ ROW_COL_TO_INDEX(r, c, COLS) ] = 75; . 오버 헤드 는 Strassen의 알고리즘에 대해 복잡성 O (n ^ 3) 또는 O (n ^ 2.81)의 행렬 곱셈을 수행 할 때 실제로 영향을 미칩니다 .
Ash Ketchum

5
@AshKetchum 인라이닝 (또는 매크로 대체)은 최적화하는 것이 합리적이지만 컴파일 된 계산은 a [x] [y]의 주소를 해결하기 위해 수행해야하는 것보다 어떻게 더 복잡합니까?
Dronz

1
@Dronz을 사용하면 a[x][y]실제로 *(*(a + x) + y)두 가지 추가 사항과 두 가지 메모리 가져 오기가 수행됩니다. 를 사용하면 a[index(x, y)]실제로 *(a + x + w*y)두 가지 추가, 하나의 곱셈 및 하나의 메모리 가져 오기가 수행됩니다. 후자는 종종이 답변에 노출 된 이유로 선호됩니다 (즉, 여분의 메모리 가져 오기를 곱셈으로 거래하는 것이 가치가 있습니다. 특히 데이터가 조각화되어 있지 않으므로 캐시 누락이 없기 때문입니다).
Boris Dalstein

118

C ++ 11에서는 가능합니다 :

auto array = new double[M][N]; 

이런 식으로 메모리가 초기화되지 않습니다. 이를 초기화하려면 대신 다음을 수행하십시오.

auto array = new double[M][N]();

샘플 프로그램 ( "g ++ -std = c ++ 11"로 컴파일) :

#include <iostream>
#include <utility>
#include <type_traits>
#include <typeinfo>
#include <cxxabi.h>
using namespace std;

int main()
{
    const auto M = 2;
    const auto N = 2;

    // allocate (no initializatoin)
    auto array = new double[M][N];

    // pollute the memory
    array[0][0] = 2;
    array[1][0] = 3;
    array[0][1] = 4;
    array[1][1] = 5;

    // re-allocate, probably will fetch the same memory block (not portable)
    delete[] array;
    array = new double[M][N];

    // show that memory is not initialized
    for(int r = 0; r < M; r++)
    {
        for(int c = 0; c < N; c++)
            cout << array[r][c] << " ";
        cout << endl;
    }
    cout << endl;

    delete[] array;

    // the proper way to zero-initialize the array
    array = new double[M][N]();

    // show the memory is initialized
    for(int r = 0; r < M; r++)
    {
        for(int c = 0; c < N; c++)
            cout << array[r][c] << " ";
        cout << endl;
    }

    int info;
    cout << abi::__cxa_demangle(typeid(array).name(),0,0,&info) << endl;

    return 0;
}

산출:

2 4 
3 5 

0 0 
0 0 
double (*) [2]

3
수업 에서이 작업을 수행해야하므로 자동을 사용할 수 없습니다. 배열에 적합한 유형은 무엇입니까?
피터 Smit

3
다음에 이것을 사용할 수 있습니까?using arr2d = double(*)[2]; arr2d array = new double[M][N];
Mohammad

3
+1 : 이것은 OP가 요청한 것입니다. 이에 대한 올바른 유형 은 상수 표현식 double (*)[M][N]이거나 double(*)[][N]M, N입니다.
Fozi

58
이 솔루션의 문제점은 차원이 런타임 값일 수 없지만 컴파일 타임에 알려야한다는 것입니다.
legends2k

4
@vsoftco 예, 사실 , 그러나 문제는 컴파일 타임에 두 치수 알 수없는 문제에 대해 구체적이었다.
legends2k

58

정적 배열 예제에서 들쭉날쭉 한 배열이 아닌 직사각형 배열을 원한다고 가정합니다. 다음을 사용할 수 있습니다.

int *ary = new int[sizeX * sizeY];

그런 다음 다음과 같은 요소에 액세스 할 수 있습니다.

ary[y*sizeX + x]

에 delete []를 사용하는 것을 잊지 마십시오 ary.


1
이것은 좋은 방법입니다. 약간의 추가 안전을 위해 sizeXXsizeY 크기의 vector <int>를 수행 할 수도 있습니다.
Dietrich Epp 2016 년

4
가장 좋은 방법은이 코드를 클래스로 감싸는 것입니다-소멸자에서 정리를 수행하고 사용자가 스스로 곱셈을 강요하지 않고 get (x, y) 및 set (x, y, val) 메소드를 구현할 수 있습니다 . operator [] 구현은 더 까다 롭지 만 가능하다고 생각합니다.
Tadeusz Kopec

47

C ++ 11 이상에서 권장하는 두 가지 일반적인 기술이 있습니다. 하나는 컴파일 시간 차원과 다른 하나입니다. 두 대답 모두 균일 한 2 차원 배열 (고르지 않은 배열)을 원한다고 가정합니다.

컴파일 시간 차원

사용 std::arraystd::array사용 후와 new힙에 넣어 :

// the alias helps cut down on the noise:
using grid = std::array<std::array<int, sizeX>, sizeY>;
grid * ary = new grid;

다시 말하지만, 컴파일 타임에 차원의 크기를 알고있는 경우에만 작동합니다.

런타임 치수

런타임에만 알려진 크기의 2 차원 배열을 달성하는 가장 좋은 방법은 클래스를 랩으로 묶는 것입니다. 클래스는 operator []1 차원 배열을 할당 한 다음 오버로드 하여 첫 번째 차원에 대한 색인을 생성합니다. C ++에서 2D 배열이 행 주요이기 때문에 작동합니다.

 논리적 형태와 1 차원 형태로 표시된 행렬

( http://eli.thegreenplace.net/2015/memory-layout-of-multi-dimensional-arrays/ 에서 가져옴 )

연속적인 메모리 시퀀스는 성능상의 이유로 좋으며 정리하기도 쉽습니다. 다음은 유용한 메소드를 많이 생략하지만 기본 아이디어를 보여주는 예제 클래스입니다.

#include <memory>

class Grid {
  size_t _rows;
  size_t _columns;
  std::unique_ptr<int[]> data;

public:
  Grid(size_t rows, size_t columns)
      : _rows{rows},
        _columns{columns},
        data{std::make_unique<int[]>(rows * columns)} {}

  size_t rows() const { return _rows; }

  size_t columns() const { return _columns; }

  int *operator[](size_t row) { return row * _columns + data.get(); }

  int &operator()(size_t row, size_t column) {
    return data[row * _columns + column];
  }
}

따라서 std::make_unique<int[]>(rows * columns)항목이 있는 배열을 만듭니다 . 우리 operator []는 행을 인덱스 할 과부하 가 발생 합니다. int *행의 시작 부분을 가리키는를 반환 한 다음 열에 대해 일반적으로 역 참조 될 수 있습니다. 참고 make_unique필요한 경우 C에서 첫 번째 선박 ++ (14) 그러나 당신이 11 ++ C에서 그것을 polyfill 수 있습니다.

이러한 유형의 구조 operator()에도 과부하가 발생하는 것이 일반적입니다 .

  int &operator()(size_t row, size_t column) {
    return data[row * _columns + column];
  }

기술적으로 내가 사용하지 않은 new여기에,하지만에서 이동하는 사소한 std::unique_ptr<int[]>int *사용 된 new/ delete.


행과 열 템플릿 매개 변수를 만들 수 있습니까?
Janus Troelsen

1
당신이 (당신이 템플릿 매개 변수를 사용하는 경우 당신이) 컴파일 타임에 크기를 알고 있다면 내가 사용하는 것이 좋습니다 std::arraystd::array들 : std::array<std::array<int, columns> rows>.
Levi Morrison

1
이것이 @kamshi의 답변과 매우 유사한 (LOC 및 개념면에서 더 간단한) 철학 아래의 정교하고 현대적인 대답이라고 말할 수 있습니까?
KcFnMi 2

그것들은 기본 기술과 관련하여 상당히 비슷합니다. 모든 차원의 모든 값을 보유하는 단일 배열이 있습니다. 그런 다음 어떻게 든 각 행의 시작 부분에 대한 포인터를 반환합니다. 실제로 클래스에는 일반적으로 복사 생성자 및 복사 할당 연산자가 있고 asserts메모리 액세스를 확인하기 위해 디버그 빌드가있는 등 더 유용한 메소드가 있습니다 . 이러한 추가는 일반적으로 작업하기가 쉽고 편리합니다.
Levi Morrison

1
또한 @KcFnMi, kamshi 의 답변 을 사용하기로 결정했다면 Benmake_unique 대신에 대한 Ben 의 의견 을 읽으십시오 new/delete.
Levi Morrison

31

이 질문은 나를 괴롭 혔습니다. 좋은 해결책이 이미 존재해야한다는 일반적인 문제입니다. 벡터 벡터보다 나은 것이거나 자신의 배열 색인을 롤링하는 것입니다.

C ++에 무언가 존재해야하지만 존재하지 않는 경우 가장 먼저 살펴볼 곳은 boost.org 입니다. 거기에 Boost Multidimensional Array Library가multi_array 있습니다. 또한 multi_array_ref1 차원 배열 버퍼를 랩핑하는 데 사용할 수 있는 클래스 도 포함합니다 .


5
나는 당신의 주장을 이해합니다. 개인적으로 왜 그렇게 어려운지 이해하지 못합니다. 솔직히 이것이 우리가 많은 프로그래머를 Java로 잃는 이유입니다. 이것들은 C ++ 사람들이 시간을 잃게 만드는 기본 기능입니다!
Oliver

나는 단지 이것을 추가 할 수도 있지만, 이것이 최선의 해결책이라고 생각하지만 일부 사람들에게는 모든 단계, 특히 초보자를 이해하기 위해 많은 두뇌가 필요하다고 생각합니다 ...;)! C ++ 프로그래머의 80 %가 typedef를 보았을 때 실패합니다.
Oliver

1
@OliverStutz는 이것이 첫 번째 위험입니다. 가장 최근의 C ++ 표준은 부담을 덜기 위해 필사적으로 노력해 왔으며 가장 좋아하는 것이 auto키워드입니다. 특히 Boost가 이미 방법을 보여 주었기 때문에 2D 어레이를 다루려고 시도하지 않은 것에 놀랐습니다.
Mark Ransom

전체 개발 자동화가 어떻게 진행되었는지는 재미있다. 이제 가장 쉬운 방법은 java이다. 나는 C ++이 도약하기를 정말로 원합니다. 그 이후로 강력하고 강력한 언어였습니다 ... 왜 이것을 사용하지 않으면 광선 검기가 있습니까!
Oliver

2
더욱이있는 C 뒤에 얼마나 멀리 C ++ 인 나에게 무엇을 괴롭히는거야 ... C99은 런타임에 정의 된 크기와 힙에 할당 된 실제 다차원 배열을 가능하게하고, C ++ (17)은 여전히 가까운 C99이 허용하는 것과 오지 않는다
cmaster-monica reinstate

27

왜 STL : vector를 사용하지 않습니까? 매우 쉽고 벡터를 삭제할 필요가 없습니다.

int rows = 100;
int cols = 200;
vector< vector<int> > f(rows, vector<int>(cols));
f[rows - 1][cols - 1] = 0; // use it like arrays

'배열'을 초기화하고 기본값을 지정하면됩니다.

const int DEFAULT = 1234;
vector< vector<int> > f(rows, vector<int>(cols, DEFAULT));

출처 : C / C ++에서 2, 3 (또는 다중) 차원 배열을 만드는 방법은 무엇입니까?


1
최고의 솔루션 IMHO
vipin8169

1
메모리 제약 때문에 STL을로드하지 않으려는 경우 좋은 해결책이 아닙니다.
katta April

2
@katta 대부분의 중요하지 않은 C ++ 프로그램은 어쨌든 STL을 사용하므로 이것은 당신을 포함한 소수의 경우에는 적합하지 않은 좋은 솔루션입니다.
Zar Shardan

내가 이해하지 못하는 것은 왜 많은 사람들이 첫 번째 색인을 행으로, 두 번째 색인을 열로 생각하는지입니다. 수학 수업에서 XY 좌표 다이어그램에 대한 반란?
Dronz

2
@Dronz C ++ 메모리 모델이기 때문입니다. 열은 행이 아니라 메모리에서 연속적입니다. 포트란에서는 다른 방법입니다.
Levi Morrison

16

2D 배열은 기본적으로 1D 포인터 배열이며 모든 포인터는 1D 배열을 가리키며 실제 데이터를 보유합니다.

여기서 N은 행이고 M은 열입니다.

동적 할당

int** ary = new int*[N];
  for(int i = 0; i < N; i++)
      ary[i] = new int[M];

가득 따르다

for(int i = 0; i < N; i++)
    for(int j = 0; j < M; j++)
      ary[i][j] = i;

인쇄

for(int i = 0; i < N; i++)
    for(int j = 0; j < M; j++)
      std::cout << ary[i][j] << "\n";

비어 있는

for(int i = 0; i < N; i++)
    delete [] ary[i];
delete [] ary;

14

GNU C ++에서 연속 다차원 배열을 할당하는 방법은 무엇입니까? "표준"구문이 작동하도록하는 GNU 확장이 있습니다.

문제는 new 연산자 []에서 비롯된 것 같습니다. 대신 new 연산자를 사용하십시오.

double (* in)[n][n] = new (double[m][n][n]);  // GNU extension

그리고 그게 전부입니다 : 당신은 C 호환 다차원 배열을 얻습니다 ...


어떤 컴파일러를 사용하고 있습니까? 배열 구문은 g ++ 4.6.4 및 4.7.3에서 컴파일 및 실행됩니다. "계산 된 값이 사용되지 않음"또는 "문은 효과가 없습니다"라는 = 전에 마지막에 경고가 표시됩니다. 그러나 g ++ 4.8.1 (완전히 c ++ 11 호환)을 사용하면 n에서 오류가 발생하고 o "연산자 new의 배열 크기는 일정해야합니다"라는 상수가 아니며 줄의 마지막을 가리 킵니다.
jbo5112

@cmaster도 double (*in)[m][n] = (double (*)[m][n])new double[k*m*n];작동하지 않습니다. n컴파일 타임에 알 수 없으므로 C2057, C2540 오류가 발생합니다 . 메모리가 올바르게 할당 되고이 메모리를 편리하게 처리하기위한 포인터 일뿐이므로 왜 그것을 할 수 없는지 이해하지 못합니다 . (VS 2010)
user1234567

2
@ user3241228 은이 gcc글을 쓸 때 나를 속 였습니다 . 공급 -std=c++11은 엄격한 표준 준수를 켜기에 충분하지 않으며, -pedantic-errors필요합니다. 나중에 플래그가 없으면 gcc실제로 C ++ 표준에 따르지 않더라도 캐스트를 행복하게 받아들입니다. 내가 아는 바로는 다차원 배열에 크게 의존하는 작업을 수행 할 때 C로 돌아가라고 조언 할 수 있습니다. C99도 C ++ 17보다 훨씬 강력합니다.
cmaster-monica reinstate

@cmaster 동적 할당 VLA는 어쨌든 구문 설탕입니다 ... 그들은 아무것도 없기 때문에 C에서 좋지만 C ++는 구문 설탕이 더 좋습니다 :)
MM

1
@MM Pity는 C ++에 런타임시에만 알려진 크기의 힙에 할당 된 진정한 연속 다차원 배열에 대한 구문 설탕을 가지고 있지 않습니다. 이것을 필요로하지 않는 한 C ++ 구문 설탕은 좋습니다. 그러나 위의 모든 것을 필요로 할 때 FORTRAN도 C ++
보다 뛰어납니다

13

typedef는 당신의 친구입니다

돌아가서 다른 많은 답변을 살펴본 후에는 다른 많은 답변이 성능 문제로 인해 어려움을 겪거나 비정상적이거나 부담스러운 구문을 사용하여 배열을 선언하거나 배열에 액세스하므로 더 자세한 설명이 필요하다는 것을 알았습니다. 요소 (또는 위의 모든 것).

먼저이 답변은 컴파일 타임에 배열의 크기를 알고 있다고 가정합니다. 그렇게 하면 최상의 성능을 제공 하고 표준 배열 구문을 사용하여 배열 요소에 액세스 할 수 있으므로 이것이 최상의 솔루션 입니다.

이것이 최상의 성능을 제공하는 이유는 모든 어레이를 연속적인 메모리 블록으로 할당하기 때문에 페이지 누락이 적고 공간적 위치가 향상 될 가능성이 있기 때문입니다. 루프에 할당하면 할당 루프가 다른 스레드 또는 프로세스에 의해 중단 될 수 있거나 (또는 ​​여러 번의 재량으로 인해) 가상 메모리 공간을 통해 여러 비 연속 페이지에 개별 어레이가 흩어질 수 있습니다. 할당자가 사용 가능한 작은 빈 메모리 블록을 채우는 할당 자.

다른 장점으로는 간단한 선언 구문과 표준 배열 액세스 구문이 있습니다.

C ++에서 new를 사용하는 경우 :

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {

typedef double (array5k_t)[5000];

array5k_t *array5k = new array5k_t[5000];

array5k[4999][4999] = 10;
printf("array5k[4999][4999] == %f\n", array5k[4999][4999]);

return 0;
}

또는 calloc을 사용하는 C 스타일 :

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {

typedef double (*array5k_t)[5000];

array5k_t array5k = calloc(5000, sizeof(double)*5000);

array5k[4999][4999] = 10;
printf("array5k[4999][4999] == %f\n", array5k[4999][4999]);

return 0;
}

1
배열 끝을 넘어서 액세스한다고해서 오류가 발생하지는 않습니다. 운이 좋으면 프로그램이 중단됩니다. 당신은 분명히 정의되지 않은 행동의 영역에 있습니다.
Michael Kristofik 2016 년

이 예제의 목적은 실제로 typedef와 new를 함께 사용하여 2D 배열을 선언하는 방법을 보여주기위한 것입니다.
Robert S. Barnes

1
나는 당신의 대답을 너무 많이 좋아했습니다. 나 자신도 typedef의 옹호자였습니다.
Fooo

12

이 문제는 15 년 동안 나를 귀찮게했으며 공급 된 모든 솔루션이 만족스럽지 않았습니다. 메모리에서 연속 다이나믹 배열을 어떻게 연속적으로 생성합니까? 오늘 나는 마침내 답을 찾았습니다. 다음 코드를 사용하면 그렇게 할 수 있습니다.

#include <iostream>

int main(int argc, char** argv)
{
    if (argc != 3)
    {
        std::cerr << "You have to specify the two array dimensions" << std::endl;
        return -1;
    }

    int sizeX, sizeY;

    sizeX = std::stoi(argv[1]);
    sizeY = std::stoi(argv[2]);

    if (sizeX <= 0)
    {
        std::cerr << "Invalid dimension x" << std::endl;
        return -1;
    }
    if (sizeY <= 0)
    {
        std::cerr << "Invalid dimension y" << std::endl;
        return -1;
    }

    /******** Create a two dimensional dynamic array in continuous memory ******
     *
     * - Define the pointer holding the array
     * - Allocate memory for the array (linear)
     * - Allocate memory for the pointers inside the array
     * - Assign the pointers inside the array the corresponding addresses
     *   in the linear array
     **************************************************************************/

    // The resulting array
    unsigned int** array2d;

    // Linear memory allocation
    unsigned int* temp = new unsigned int[sizeX * sizeY];

    // These are the important steps:
    // Allocate the pointers inside the array,
    // which will be used to index the linear memory
    array2d = new unsigned int*[sizeY];

    // Let the pointers inside the array point to the correct memory addresses
    for (int i = 0; i < sizeY; ++i)
    {
        array2d[i] = (temp + i * sizeX);
    }



    // Fill the array with ascending numbers
    for (int y = 0; y < sizeY; ++y)
    {
        for (int x = 0; x < sizeX; ++x)
        {
            array2d[y][x] = x + y * sizeX;
        }
    }



    // Code for testing
    // Print the addresses
    for (int y = 0; y < sizeY; ++y)
    {
        for (int x = 0; x < sizeX; ++x)
        {
            std::cout << std::hex << &(array2d[y][x]) << ' ';
        }
    }
    std::cout << "\n\n";

    // Print the array
    for (int y = 0; y < sizeY; ++y)
    {
        std::cout << std::hex << &(array2d[y][0]) << std::dec;
        std::cout << ": ";
        for (int x = 0; x < sizeX; ++x)
        {
            std::cout << array2d[y][x] << ' ';
        }
        std::cout << std::endl;
    }



    // Free memory
    delete[] array2d[0];
    delete[] array2d;
    array2d = nullptr;

    return 0;
}

sizeX = 20 및 sizeY = 15 값으로 프로그램을 호출하면 출력은 다음과 같습니다.

0x603010 0x603014 0x603018 0x60301c 0x603020 0x603024 0x603028 0x60302c 0x603030 0x603034 0x603038 0x60303c 0x603040 0x603044 0x603048 0x60304c 0x603050 0x603054 0x603058 0x60305c 0x603060 0x603064 0x603068 0x60306c 0x603070 0x603074 0x603078 0x60307c 0x603080 0x603084 0x603088 0x60308c 0x603090 0x603094 0x603098 0x60309c 0x6030a0 0x6030a4 0x6030a8 0x6030ac 0x6030b0 0x6030b4 0x6030b8 0x6030bc 0x6030c0 0x6030c4 0x6030c8 0x6030cc 0x6030d0 0x6030d4 0x6030d8 0x6030dc 0x6030e0 0x6030e4 0x6030e8 0x6030ec 0x6030f0 0x6030f4 0x6030f8 0x6030fc 0x603100 0x603104 0x603108 0x60310c 0x603110 0x603114 0x603118 0x60311c 0x603120 0x603124 0x603128 0x60312c 0x603130 0x603134 0x603138 0x60313c 0x603140 0x603144 0x603148 0x60314c 0x603150 0x603154 0x603158 0x60315c 0x603160 0x603164 0x603168 0x60316c 0x603170 0x603174 0x603178 0x60317c 0x603180 0x603184 0x603188 0x60318c 0x603190 0x603194 0x603198 0x60319c 0x6031a0 0x6031a4 0x6031a8 0x6031ac 0x6031b0 0x6031b4 0x6031b8 0x6031bc 0x6031c0 0x6031c4 0x6031c8 0x6031cc 0x6031d0 0x6031d4 0x6031d8 0x6031dc 0x6031e0 0x6031e4 0x6031e8 0x6031ec 0x6031f0 0x6031f4 0x6031f8 0x6031fc 0x603200 0x603204 0x603208 0x60320c 0x603210 0x603214 0x603218 0x60321c 0x603220 0x603224 0x603228 0x60322c 0x603230 0x603234 0x603238 0x60323c 0x603240 0x603244 0x603248 0x60324c 0x603250 0x603254 0x603258 0x60325c 0x603260 0x603264 0x603268 0x60326c 0x603270 0x603274 0x603278 0x60327c 0x603280 0x603284 0x603288 0x60328c 0x603290 0x603294 0x603298 0x60329c 0x6032a0 0x6032a4 0x6032a8 0x6032ac 0x6032b0 0x6032b4 0x6032b8 0x6032bc 0x6032c0 0x6032c4 0x6032c8 0x6032cc 0x6032d0 0x6032d4 0x6032d8 0x6032dc 0x6032e0 0x6032e4 0x6032e8 0x6032ec 0x6032f0 0x6032f4 0x6032f8 0x6032fc 0x603300 0x603304 0x603308 0x60330c 0x603310 0x603314 0x603318 0x60331c 0x603320 0x603324 0x603328 0x60332c 0x603330 0x603334 0x603338 0x60333c 0x603340 0x603344 0x603348 0x60334c 0x603350 0x603354 0x603358 0x60335c 0x603360 0x603364 0x603368 0x60336c 0x603370 0x603374 0x603378 0x60337c 0x603380 0x603384 0x603388 0x60338c 0x603390 0x603394 0x603398 0x60339c 0x6033a0 0x6033a4 0x6033a8 0x6033ac 0x6033b0 0x6033b4 0x6033b8 0x6033bc 0x6033c0 0x6033c4 0x6033c8 0x6033cc 0x6033d0 0x6033d4 0x6033d8 0x6033dc 0x6033e0 0x6033e4 0x6033e8 0x6033ec 0x6033f0 0x6033f4 0x6033f8 0x6033fc 0x603400 0x603404 0x603408 0x60340c 0x603410 0x603414 0x603418 0x60341c 0x603420 0x603424 0x603428 0x60342c 0x603430 0x603434 0x603438 0x60343c 0x603440 0x603444 0x603448 0x60344c 0x603450 0x603454 0x603458 0x60345c 0x603460 0x603464 0x603468 0x60346c 0x603470 0x603474 0x603478 0x60347c 0x603480 0x603484 0x603488 0x60348c 0x603490 0x603494 0x603498 0x60349c 0x6034a0 0x6034a4 0x6034a8 0x6034ac 0x6034b0 0x6034b4 0x6034b8 0x6034bc 

0x603010: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
0x603060: 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 
0x6030b0: 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 
0x603100: 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 
0x603150: 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 
0x6031a0: 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 
0x6031f0: 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 
0x603240: 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 
0x603290: 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 
0x6032e0: 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 
0x603330: 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 
0x603380: 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 
0x6033d0: 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 
0x603420: 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 
0x603470: 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299

보시다시피, 다차원 배열은 연속적으로 메모리에 있으며 두 개의 메모리 주소가 겹치지 않습니다. 배열을 해제하는 루틴조차도 모든 단일 열 (또는 배열을 보는 방법에 따라 행)에 메모리를 동적으로 할당하는 표준 방법보다 간단합니다. 배열은 기본적으로 두 개의 선형 배열로 구성되므로이 두 개만 해제해야합니다.

이 방법은 동일한 개념으로 2 차원 이상으로 확장 될 수 있습니다. 여기서는하지 않겠지 만 그 아이디어를 이해하면 간단한 작업입니다.

이 코드가 도움이 되었으면 좋겠습니다.


1
여전히 추가 포인터 배열이 있습니다. 배열을 사용하는 코드는 가정 할 수 없기 때문에 추가 간접 계층을 수행해야합니다 array2d[i] = buffer + i * sizeX. 따라서 이것은 약간 도움이되지만 배열을 사용하는 코드에서는 컴파일러가 포인터를 증가시켜 배열을 스캔 할 수는 없습니다.
Peter Cordes

4
그렇습니다. 이것은 정확히하는 방법입니다. 그러나 C ++ 방식으로 C ++ make_unique<int[]>(sizeX*sizeY)에서 연속 스토리지 make_unique<int*[]>(sizeX)를 설정하고 포인터에 대한 스토리지를 설정하는 데 사용합니다 (표시하는 것과 동일한 방식으로 할당해야 함). 이렇게하면 delete[]끝에서 두 번 전화 할 필요가 없습니다 .
벤 Voigt

이 답변은 @BenVoigt 의견을 더 고려하여 나에게 많은 의미가 있습니다. @PeterCordes가 참조하는 추가 포인터 배열은 temp무엇입니까? 이점 (컴파일 타임에 알 수없는 차원의 연속체 2d 배열)을 고려할 때 매달려있는 것을 신경 쓰지 않을 것입니다. @PeterCordes의 의미가 무엇인지 모릅니다 extra layer of indirection. 무엇입니까? 왜 괄호, array2d[i] = (temp + i * sizeX);
KcFnMi

delete [] array2d [0]은 delete [] temp와 동일합니까?
KcFnMi

6

이 답변의 목적은 다른 사람들이 아직 다루지 않은 새로운 것을 추가하는 것이 아니라 @Kevin Loney의 답변을 확장하는 것입니다.

간단한 선언을 사용할 수 있습니다.

int *ary = new int[SizeX*SizeY]

액세스 구문은 다음과 같습니다.

ary[i*SizeY+j]     // ary[i][j]

그러나 이것은 대부분 성가 시며 혼란을 초래할 수 있습니다. 따라서 다음과 같이 매크로를 정의 할 수 있습니다.

#define ary(i, j)   ary[(i)*SizeY + (j)]

이제 매우 유사한 구문을 사용하여 배열에 액세스 할 수 있습니다 ary(i, j) // means ary[i][j]. 이것은 단순하고 아름답다는 장점이 있으며, 동시에 인덱스 대신 표현식을 사용하는 것이 더 간단하고 혼란스럽지 않습니다.

예를 들어, ary [2 + 5] [3 + 8]에 액세스하려면 ary(2+5, 3+8)복잡한 모양 대신 쓸 수 있습니다. ary[(2+5)*SizeY + (3+8)]즉, 괄호를 절약하고 가독성을 높일 수 있습니다.

주의 사항 :

  • 구문은 매우 유사하지만 동일하지 않습니다.
  • 배열을 다른 함수에 SizeY전달하는 경우 동일한 이름으로 전달해야합니다 (또는 전역 변수로 선언).

또는 여러 함수에서 배열을 사용해야하는 경우 다음과 같이 매크로 정의에서 다른 매개 변수로 SizeY를 추가 할 수 있습니다.

#define ary(i, j, SizeY)  ary[(i)*(SizeY)+(j)]

당신은 아이디어를 얻습니다. 물론 이것은 너무 길어 유용하지는 않지만 여전히 +와 *의 혼동을 막을 수 있습니다.

이것은 반드시 권장되지는 않으며 대부분의 숙련 된 사용자가 나쁜 습관으로 비난받을 수 있지만 우아함으로 인해 공유하는 것을 거부 할 수 없었습니다.

편집 :
여러 배열에서 작동하는 휴대용 솔루션을 원하면 다음 구문을 사용할 수 있습니다.

#define access(ar, i, j, SizeY) ar[(i)*(SizeY)+(j)]

그런 다음 액세스 구문을 사용하여 크기에 상관없이 모든 배열을 호출에 전달할 수 있습니다.

access(ary, i, j, SizeY)      // ary[i][j]

추신 : 나는 이것을 테스트했으며 g ++ 14 및 g ++ 11 컴파일러에서 동일한 구문이 작동합니다 (lvalue와 rvalue 모두).


4

이것을 시도하십시오 :

int **ary = new int* [sizeY];
for (int i = 0; i < sizeY; i++)
    ary[i] = new int[sizeX];

2

여기에는 두 가지 옵션이 있습니다. 첫 번째는 배열의 배열 또는 포인터의 포인터 개념을 보여줍니다. 이미지에서 볼 수 있듯이 주소가 인접하기 때문에 두 번째 주소를 선호합니다.

여기에 이미지 설명을 입력하십시오

#include <iostream>

using namespace std;


int main(){

    int **arr_01,**arr_02,i,j,rows=4,cols=5;

    //Implementation 1
    arr_01=new int*[rows];

    for(int i=0;i<rows;i++)
        arr_01[i]=new int[cols];

    for(i=0;i<rows;i++){
        for(j=0;j<cols;j++)
            cout << arr_01[i]+j << " " ;
        cout << endl;
    }


    for(int i=0;i<rows;i++)
        delete[] arr_01[i];
    delete[] arr_01;


    cout << endl;
    //Implementation 2
    arr_02=new int*[rows];
    arr_02[0]=new int[rows*cols];
    for(int i=1;i<rows;i++)
        arr_02[i]=arr_02[0]+cols*i;

    for(int i=0;i<rows;i++){
        for(int j=0;j<cols;j++)
            cout << arr_02[i]+j << " " ;
        cout << endl;
    }

    delete[] arr_02[0];
    delete[] arr_02;


    return 0;
}

1

프로젝트가 CLI (공용 언어 런타임 지원) 인 경우 :

작성할 때 얻는 것이 아닌 배열 클래스를 사용할 수 있습니다.

#include <array>
using namespace std;

다시 말해서 std 네임 스페이스를 사용할 때와 배열 헤더를 포함 할 때 얻는 관리되지 않는 배열 클래스가 아니라 std 네임 스페이스와 배열 헤더에 정의 된 관리되지 않는 배열 클래스가 아니라 CLI의 관리되는 클래스 배열입니다.

이 클래스를 사용 하면 원하는 순위 의 배열을 만들 수 있습니다 .

아래 코드는 2 개의 행과 3 개의 열과 int 유형의 새로운 2 차원 배열을 만들고 이름을 "arr"로 지정합니다.

array<int, 2>^ arr = gcnew array<int, 2>(2, 3);

이제 배열의 요소에 이름으로 액세스하고 하나의 제곱 괄호 쓰고 []그 안에 행과 열을 추가하고 쉼표로 구분할 수 있습니다, .

아래 코드는 위의 이전 코드에서 이미 만든 배열의 두 번째 행과 첫 번째 열의 요소에 액세스합니다.

arr[0, 1]

이 줄만 쓰는 것은 해당 셀의 값을 읽는 것입니다. 즉,이 셀의 값을 가져옵니다. = 해당 셀의 값을 쓰려고합니다. 즉,이 셀의 값을 설정합니다. 물론 숫자 만 (int, float, double, __int16, __int32, __int64 등)에 + =,-=, * = 및 / = 연산자를 사용할 수 있지만 이미 알고 있어야합니다.

프로젝트가 CLI 가 아닌 경우 #include <array>물론 std 네임 스페이스의 관리되지 않는 배열 클래스를 사용할 수 있지만 문제는이 배열 클래스가 CLI 배열과 다르다는 것입니다. 이 유형의 배열 만들기는 ^기호와 gcnew키워드 를 제거해야한다는 점을 제외하고 CLI와 동일합니다 . 그러나 불행히도 두 번째 INT 매개 변수를 <>괄호는 지정 길이 (즉, 크기) 배열의, 하지 의 순위를!

이런 종류의 배열에서 순위를 지정할 수있는 방법은 없습니다. rank는 CLI 배열의 기능 일뿐입니다. .

std 배열은 c ++에서 일반 배열처럼 작동합니다. 예를 들어 포인터를 사용하여 정의 int*한 다음 new int[size]포인터를 사용하지 않고 정의 int arr[size]하십시오 .c ++의 일반 배열과 달리 std 배열은 배열의 요소와 함께 사용할 수있는 함수를 제공합니다. 채우기, 시작, 끝, 크기 등과 같지만 일반 배열은 아무것도 제공 하지 않습니다 .

그러나 여전히 표준 배열은 일반 C ++ 배열과 같은 1 차원 배열입니다. 그러나 다른 사람들이 일반적인 c ++ 1 차원 배열을 2 차원 배열로 만드는 방법에 대해 제안한 솔루션 덕분에 Mehrdad Afshari의 아이디어에 따라 동일한 아이디어를 표준 배열에 적용 할 수 있습니다. 예를 들어 다음 코드를 작성할 수 있습니다.

array<array<int, 3>, 2> array2d = array<array<int, 3>, 2>();

이 코드 줄은 "jugged array"를 생성하는데 , 이는 각 셀이 다른 1 차원 배열이거나이를 가리키는 1 차원 배열입니다.

1 차원 배열의 1 차원 배열이 모두 길이 / 크기가 같으면 array2d 변수를 실제 2 차원 배열로 취급 할 수 있으며, 특수한 방법을 사용하여 행 또는 열을 처리 할 수 ​​있습니다. 2D 배열에서 std 배열은 지원합니다.

Kevin Loney의 솔루션을 사용할 수도 있습니다.

int *ary = new int[sizeX*sizeY];

// ary[i][j] is then rewritten as
ary[i*sizeY+j]

그러나 std 배열을 사용하면 코드가 다르게 보일 것입니다.

array<int, sizeX*sizeY> ary = array<int, sizeX*sizeY>();
ary.at(i*sizeY+j);

그리고 여전히 std 배열의 고유 기능을 가지고 있습니다.

[]괄호를 사용하여 std 배열의 요소에 계속 액세스 할 수 있으며 at함수 를 호출 할 필요가 없습니다 . 또한 std 배열의 총 요소 수를 계산하고 유지하고 반복하는 대신 해당 값을 사용하는 새로운 int 변수를 정의하고 지정할 수 있습니다sizeX*sizeY

고유 한 2 차원 배열 일반 클래스를 정의하고 2 차원 배열 클래스의 생성자를 정의하여 2 개의 정수를 수신하여 새 2 차원 배열의 행 및 열 수를 지정하고 정수의 2 개의 매개 변수를 수신하는 get 함수를 정의 할 수 있습니다. 2 차원 배열의 요소에 액세스하여 값을 반환하고 3 개의 매개 변수를받는 함수를 설정합니다. 2 개의 첫 번째는 2 차원 배열의 행과 열을 지정하는 정수이고 세 번째 매개 변수는 요소. 유형은 일반 클래스에서 선택한 유형에 따라 다릅니다.

당신은 사용하여 모든이를 구현 할 수있을 것 중 하나 정상적인 C ++ 배열 (포인터 또는없이) 또는 두 개의 같은 또는 다른 사람이 제안하는 아이디어의 표준 배열 사용을하고 CLI 배열처럼 사용하기 쉬운 그것을 만들 C #에서 정의, 할당 및 사용할 수있는 차원 배열입니다.


1

포인터를 사용하여 배열을 정의하여 시작하십시오 (1 행).

int** a = new int* [x];     //x is the number of rows
for(int i = 0; i < x; i++)
    a[i] = new int[y];     //y is the number of columns

1

아래 예제가 도움이 될 수 있습니다.

int main(void)
{
    double **a2d = new double*[5]; 
    /* initializing Number of rows, in this case 5 rows) */
    for (int i = 0; i < 5; i++)
    {
        a2d[i] = new double[3]; /* initializing Number of columns, in this case 3 columns */
    }

    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            a2d[i][j] = 1; /* Assigning value 1 to all elements */
        }
    }

    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            cout << a2d[i][j] << endl;  /* Printing all elements to verify all elements have been correctly assigned or not */
        }
    }

    for (int i = 0; i < 5; i++)
        delete[] a2d[i];

    delete[] a2d;


    return 0;
}

1

메모리에 순차적으로 할당되는 요소의 2D 정수 배열을 원하면 다음과 같이 선언해야합니다.

int (*intPtr)[n] = new int[x][n]

여기서 x 대신 차원을 작성할 수 있지만 n 은 두 위치에서 동일해야합니다. 예

int (*intPtr)[8] = new int[75][8];
intPtr[5][5] = 6;
cout<<intPtr[0][45]<<endl;

6을 인쇄해야합니다.


0

어떤 경우에는 나에게 가장 적합한 솔루션을 남겨 두었습니다. 특히 배열의 크기를 [크기?]로 알고 있다면 예를 들어 char [20]의 다양한 크기의 배열이 필요한 경우 char 배열에 매우 유용합니다.

int  size = 1492;
char (*array)[20];

array = new char[size][20];
...
strcpy(array[5], "hola!");
...
delete [] array;

열쇠는 배열 선언에서 괄호입니다.


StackOverflow는 영어 만 사용하므로 질문을 번역하십시오.
M. Mimpen

0

나는 이것을 우아하지는 않지만 FAST, EASY 및 WORKING 시스템을 사용했습니다. 시스템이 큰 크기의 배열을 만들고 부품에 액세스 할 수있는 유일한 방법은 부품을 자르지 않는 것이므로 왜 작동하지 않는지 알 수 없습니다.

#define DIM 3
#define WORMS 50000 //gusanos

void halla_centros_V000(double CENW[][DIM])
{
    CENW[i][j]=...
    ...
}


int main()
{
    double *CENW_MEM=new double[WORMS*DIM];
    double (*CENW)[DIM];
    CENW=(double (*)[3]) &CENW_MEM[0];
    halla_centros_V000(CENW);
    delete[] CENW_MEM;
}

0

다음 답변이 제공되지 않았는지 확실하지 않지만 2d 배열 할당에 로컬 최적화를 추가하기로 결정했습니다 (예 : 정사각형 행렬은 하나의 할당만으로 수행됩니다). int** mat = new int*[n]; mat[0] = new int [n * n];

그러나 위 할당의 선형성 때문에 삭제는 다음과 같습니다. delete [] mat[0]; delete [] mat;


: 이미 바로이 질문에 대한 답변에서 언급 stackoverflow.com/a/27672888/103167 여기에 스마트 포인터 버전 : stackoverflow.com/a/29375830/103167
벤 보이트

-1

2D 배열을 동적으로 선언 :

    #include<iostream>
    using namespace std;
    int main()
    {
        int x = 3, y = 3;

        int **ptr = new int *[x];

        for(int i = 0; i<y; i++)
        {
            ptr[i] = new int[y];
        }
        srand(time(0));

        for(int j = 0; j<x; j++)
        {
            for(int k = 0; k<y; k++)
            {
                int a = rand()%10;
                ptr[j][k] = a;
                cout<<ptr[j][k]<<" ";
            }
            cout<<endl;
        }
    }

위의 코드에서 우리는 이중 포인터를 가져 와서 동적 메모리를 할당하고 열 값을 부여했습니다. 여기서 할당 된 메모리는 열에 만 해당되며 이제 행의 경우 for 루프가 필요하고 모든 행의 값을 동적 메모리로 지정하십시오. 이제 2D 배열을 사용하는 것처럼 포인터를 사용할 수 있습니다. 위의 예제에서 2D 배열 (포인터)에 난수를 할당했습니다. 이것은 2D 배열의 DMA에 관한 것입니다.


-3

동적 배열을 만들 때 이것을 사용하고 있습니다. 수업이나 구조체가 있다면. 그리고 이것은 작동합니다. 예:

struct Sprite {
    int x;
};

int main () {
   int num = 50;
   Sprite **spritearray;//a pointer to a pointer to an object from the Sprite class
   spritearray = new Sprite *[num];
   for (int n = 0; n < num; n++) {
       spritearray[n] = new Sprite;
       spritearray->x = n * 3;
  }

   //delete from random position
    for (int n = 0; n < num; n++) {
        if (spritearray[n]->x < 0) {
      delete spritearray[n];
      spritearray[n] = NULL;
        }
    }

   //delete the array
    for (int n = 0; n < num; n++) {
      if (spritearray[n] != NULL){
         delete spritearray[n];
         spritearray[n] = NULL;
      }
    }
    delete []spritearray;
    spritearray = NULL;

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