이차원 배열 동적 할당 문제

rlqja6266의 이미지

C++에서 클래스를 2차원 배열로 동적할당해 쓰고 싶습니다.

typedef class
{
public:
	int score;
	char arrow;
}matrix;
 
matrix** term = new matrix*[m];
	for(int i = 0; i < m; i++)
	{
		term[i] = new matrix[m];
	}	

이런 식으로 구현했는데요,

행과 열이 구분이 안됩니다.

예를 들어 5x3 크기의 2차원 배열이라면

term[4][3]과 term[3][4]를 구분하지 못하고 중복해서 입력이 되는 등의 오류가 있습니다.

5행 3열로 제대로 만들어 졌다면, 4열이 없어야 하지 않나요?

행과 열을 구분해서 쓰려면 어떻게 해야하나요?

HDNua의 이미지

워낙 고수 분들이 많아 답변 드리기가 겁나네요.. ㅠ
제가 생각하는 대로 말씀드려보지만 수정해주시면 감사하게 받겠습니다.
일단 저 반복문은 term[m][m];의 정사각형꼴 배열을 만드는 구문입니다.

컴퓨터는 메모리를 할당할 때 행과 열로 배치하지 않고, 그냥 일자로 죽 이어버립니다.
5행 3열의 메모리 arr1[5][3]이라면 이렇게 배치되는 것이죠.
[ [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3] ]
3행 5열의 메모리 arr2[3][5]는 이렇게 배치됩니다.
[ [1, 2, 3, 1, 2], [3, 1, 2, 3, 1], [2, 3, 1, 2, 3] ]

이때 주의할 점은, 컴파일러가 배열 크기가 맞는지를 검사하지 않는다는 점입니다.
단순히 정해진 위치에서 얼마나 떨어져있는가만 넘겨줘요.
예를 들면, arr[5][3]의 원소 arr[1][0]는 arr[0][3]라고 접근해도 아무런 문제가 없습니다.
( sizeof(type)*(3*1+0) == sizeof(type)*(3*0+3) )
열의 길이는 3인데 열의 4번째 원소에 접근해도 제대로 실행이 된다는 뜻입니다.

이런 경우는, 접근자 함수를 클래스에 만들어주고 이 함수를 실행하는 게 좋아보입니다.
class Test{ private: int x; public: int getX() const; void setX(int x); };
class TestArr{ private: int m, n; Test** arr; public: TestArr(int m, int n); ~TestArr(); const Test* getTest(int m, int n) const; void setTest(int m, int n, const Test& test); };

생성자에서 m * n 크기의 배열을 만들어주고, 소멸자에서 이 배열을 삭제합니다.
getTest(int, int) 함수에서 배열 크기를 넘었는지 아닌지를 검사하여, 올바른 값이면 해당 변수의 주소 값을, 이외의 경우 NULL을 리턴하게 합니다.
setTest(int, int, const Test&) 함수에서 마찬가지로 배열 크기를 검사하여, 올바른 값이면 대입하고 그 외의 경우 throw 시킵니다.

이렇게 하시면 되리라 생각합니다. 참고로 2차원 배열의 경우 이렇게 보면 편합니다. int arr[행][열];

저는 이렇게 생각했습니다.

klyx의 이미지

한가지말씀드리자면 T t[m][n]으로 할당된 메모리와 T **t = new t*[m]; for (int i=0; i<m; ++i) t[i] = new t; 로 할당된 메모리는 구조가 다릅니다.
전자의 경우는 결국엔 1차원 배열이기 때문에 적으신 대로 생각해도 되는데, 후자의 경우는 실제로 메모리상에서도 2차원입니다.

T t[5][3]이라면

t t t t t t t t t t t t t t t

메모리상에 이렇게 들어가지만 동일한 목적의 동적할당된 2차원 배열은

t[0]-> t t t
t[1]-> t t t
t[2]-> t t t
t[3]-> t t t
t[4]-> t t t

이렇게 들어갑니다.(각각의 2중 포인터에 새로 할당을 해주니까 당연하겠죠?)
따라서 전자에서는 t[1][0]==t[0][3]이지만 후자에서는 성립하지 않습니다. 값이 다를 뿐만 아니라 t[0][3]은 할당되지 않은 영역에 대한 참조가 됩니다.

HDNua의 이미지

배열 첫 번째 원소에서 총 크기만큼 잡아주고 다른 부분은 대입만 해주는 방식과 헷갈렸습니다. ㅎㅎ
수정 감사합니다!

저는 이렇게 생각했습니다.

klyx의 이미지

우선 크기가 고정되지 않아서 동적할당을 해야한다면 컴파일 타임에 할 수 있는 건 없습니다.
적으신 문제는 행과 열이 구분되지 않는 문제가 아니라, 할당되지 않은 영역에 접근하는게 문제입니다.
어느쪽이 행이고 어느쪽이 열이냐는 사용자가 맘대로 정한거지 컴퓨터가 정해주는게 아니니까요.
런타임에라도 오류를 지적하기 위한 방법으로는 단순한 배열을 쓰지 말고, 매트릭스를 나타내는 클래스를 만들어서, 첨자 접근할 때 적합한 범위인지 판단해서 적합하지 않으면 적당히 에러를 내던 하는 방법으로 짤 수 있겠지요.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.