[C++] 배열의 크기를 리사이징할려면 어떻게 해야하는지..

assa의 이미지

네이버 게시판을 참고해서 대충 이렇게 만들어봤는데요..

char *resize(char *, int a);
int main(){

   char *arr= new char[10];
   arr= resize(NULL, 100);

   delete arr;

   return 0;
}

char *resize(char *re_arr, int a){
   delete re_arr;

   re_arr= new char[a];

}

에러가 나네요..(무한 루프로 delete, create하니까요...)

다른 방법이 있는지..알고 싶습니다...

보통 어떻게 배열을 리사이징하나요?

리사이징이라는 표현이 맞기는 한건지도 궁금...^^;;

좋은 하루 되세요

익명 사용자의 이미지

vector를 쓰세요.
(저 코드에서는 resize함수 내에서 re_arr을 리턴하지 않은데다 resize함수 내에서는 원하는 포인터가 아닌 NULL를 delete하므로 문제가 생깁니다.)

서지훈의 이미지

malloc() 과 realloc() 이것 밖에는 모르겠군요.
배열이 아니라 당연히 pointer로 사용을 하셔야 하고요.
이만한게 있을지 ㅡㅡㅋ

<어떠한 역경에도 굴하지 않는 '하양 지훈'>

#include <com.h> <C2H5OH.h> <woman.h>
do { if (com) hacking(); if (money) drinking(); if (women) loving(); } while (1);

singlet의 이미지

assa wrote:
char *resize(char *re_arr, int a){
   delete re_arr;
   re_arr= new char[a];
}

new[] 를 사용하셨으므로 짝이 맞는 delete[] 를 사용하셔야 합니다.
char *resize(char *re_arr, int a){
   delete[] re_arr;
   re_arr= new char[a];
}

그건 그렇고, C++ 에서 배열의 크기를 변화시킬 필요가 있다면 배열 대신 vector 를 쓰는 게 맞습니다. 멤버 함수 resize() 를 이용하면 됩니다.

무슨 이유로든 간에 vector 를 쓰지 않고 재할당을 하시겠다면 realloc() 쪽이 좋습니다. (물론 이 경우에는 new / delete 대신에 malloc() / free() 를 쓰셔야 하며 객체 생성 / 파괴도 직접 해야 합니다.)

Anonymous wrote:
resize함수 내에서는 원하는 포인터가 아닌 NULL를 delete하므로 문제가 생깁니다.

문제가 생기지 않습니다. Null pointer 를 delete 하는 것은 적법한 행동으로서 어떤 효과도, 어떤 문제도 일으키지 않습니다. (C++98 3.7.3.2)
익명 사용자의 이미지

물론 에러가 발생하진 않죠 -_-;
원하는 동작을 얻을 수 없다는 뜻이었습니다.

익명 사용자의 이미지

이중 포인터를 써야 하는 상황이 아닐지 조심스럽게 추측해 봅니다.

void resize(char **re_arr, int a){
delete[] *re_arr;
*re_arr= new char[a];
}

// main
char *arr= new char[10];
resize(&arr, 100);

원본이 보존되지 않는다는건 물론 알고 계시겠지요.. 총총

ixevexi의 이미지

~,.~ wrote:
이중 포인터를 써야 하는 상황이 아닐지 조심스럽게 추측해 봅니다.

void resize(char **re_arr, int a){
delete[] *re_arr;
*re_arr= new char[a];
}

// main
char *arr= new char[10];
resize(&arr, 100);

원본이 보존되지 않는다는건 물론 알고 계시겠지요.. 총총

그냥 단일 포인터를 써도 될것 같은데요?

C++, 그리고 C++....
죽어도 C++

wafe의 이미지

new[]로 만든 것을 delete로 지우면 메모리릭이 생길 겁니다. 그리고 resize 함수에서 리턴을 하지 않고 있네요? 새로 만든 배열 포인터를 리턴하는 부분이 없어서 무효입니다.

char *resize(char *re_arr, int a)
{
    delete[] re_arr;
    re_arr = new char[a];
    return re_arr;
}

arr = new char[10];
arr = resize(NULL, 100); 

또 위에서 처럼 호출하면 역시 메모리릭이 나겠네요. resize에 arr을 전달해야 메모리릭이 없겠습니다.
arr = resize(arr, 100);

Heejoon Lee

익명 사용자의 이미지

void resize(char *, int a);
int main(){

char *arr= new char[10];
resize(arr, 100);

delete[] arr;

return 0;
}

void resize(char *re_arr, int a){

if(re_arr != NULL)
delete[] re_arr;

re_arr= new char[a];

}

지금 컴파일러가 없어서 실행은 못시켜 봤습니다.
다른 분들이 말씀하신대로 C++에서 리사이징 하신다면 vector를 사용하는게
좋을것 같습니다.
c++에 별로 경험이 없어서 정확한 답볍은 못들겠습니다.
resize(char *, int a) 함수는 지금 argument로 char 포인터를 받고있습니다. 포인터는 즉 메모리의 주소를 말하는것이고, 메모리의 주소를 알고있다면 리턴을 지켜주지 않아도 그 변수에 직접 컨트롤 할 수 있습니다.
main()에서 넘어온 그 변수의 메모리 주소를 가지고 현재의 메모리를 제거하고
새로운 메모리를 활당 할...수 있을것 같군요.
call by reference의 개념을 생각하시면 될것 같습니다.

프로그램을 손을..놓은지가 조금 오래되어서 정확하지 못한 부분이 많습니다. 이거 주절주절 거리기만 하고 별도움이 못됐군요.. 그럼

kane의 이미지

지나가는 사람.... wrote:
void resize(char *, int a);
int main(){

char *arr= new char[10];
resize(arr, 100);

delete[] arr;

return 0;
}

void resize(char *re_arr, int a){

if(re_arr != NULL)
delete[] re_arr;

re_arr= new char[a];

}

지금 컴파일러가 없어서 실행은 못시켜 봤습니다.
다른 분들이 말씀하신대로 C++에서 리사이징 하신다면 vector를 사용하는게
좋을것 같습니다.
c++에 별로 경험이 없어서 정확한 답볍은 못들겠습니다.
resize(char *, int a) 함수는 지금 argument로 char 포인터를 받고있습니다. 포인터는 즉 메모리의 주소를 말하는것이고, 메모리의 주소를 알고있다면 리턴을 지켜주지 않아도 그 변수에 직접 컨트롤 할 수 있습니다.
main()에서 넘어온 그 변수의 메모리 주소를 가지고 현재의 메모리를 제거하고
새로운 메모리를 활당 할...수 있을것 같군요.
call by reference의 개념을 생각하시면 될것 같습니다.

프로그램을 손을..놓은지가 조금 오래되어서 정확하지 못한 부분이 많습니다. 이거 주절주절 거리기만 하고 별도움이 못됐군요.. 그럼


제 기억에 C는 call by value 였던 것 같은데...
re_arr로 arr이 가리키는 영역에 접근할 수는 있지만 arr 값을 직접 변경할 수는 없습니다. re_arr과 arr은 서로 다른 변수이기 때문에 re_arr 값을 변경해도 arr 값은 변경되지 않습니다. 메모리 재할당을 위해서는 pointer of pointer를 인자로 받아야 합니다.
아래 코드는 심심해서 작성해 본 것 입니다.
template<T> T* resize(T** t,int size)
{
  T* tmp = new T[size];
  memcpy(tmp,*t,sizeof(T)*size);
  *t = tmp;
  return tmp;
}
wafe의 이미지

지나가는 사람.... wrote:

main()에서 넘어온 그 변수의 메모리 주소를 가지고 현재의 메모리를 제거하고
새로운 메모리를 활당 할...수 있을것 같군요.
call by reference의 개념을 생각하시면 될것 같습니다.

call by reference의 개념을 잘못 생각하고 계십니다. reference가 가리키고 있는 대상의 값을 바꾸는 것이야 대상을 조작하는 것이므로 상관없겠지만, 새로운 대상을 가리키도록 하는 것은 불가능합니다. 포인터도 단순히 값일 뿐입니다. 메모리의 주소값을 담고 있는 거죠. 주소를 값으로 전달하는 겁니다.

Heejoon Lee

happycat의 이미지

kane wrote:
지나가는 사람.... wrote:
void resize(char *, int a);
int main(){

char *arr= new char[10];
resize(arr, 100);

delete[] arr;

return 0;
}

void resize(char *re_arr, int a){

if(re_arr != NULL)
delete[] re_arr;

re_arr= new char[a];

}

지금 컴파일러가 없어서 실행은 못시켜 봤습니다.
다른 분들이 말씀하신대로 C++에서 리사이징 하신다면 vector를 사용하는게
좋을것 같습니다.
c++에 별로 경험이 없어서 정확한 답볍은 못들겠습니다.
resize(char *, int a) 함수는 지금 argument로 char 포인터를 받고있습니다. 포인터는 즉 메모리의 주소를 말하는것이고, 메모리의 주소를 알고있다면 리턴을 지켜주지 않아도 그 변수에 직접 컨트롤 할 수 있습니다.
main()에서 넘어온 그 변수의 메모리 주소를 가지고 현재의 메모리를 제거하고
새로운 메모리를 활당 할...수 있을것 같군요.
call by reference의 개념을 생각하시면 될것 같습니다.

프로그램을 손을..놓은지가 조금 오래되어서 정확하지 못한 부분이 많습니다. 이거 주절주절 거리기만 하고 별도움이 못됐군요.. 그럼


제 기억에 C는 call by value 였던 것 같은데...
re_arr로 arr이 가리키는 영역에 접근할 수는 있지만 arr 값을 직접 변경할 수는 없습니다. re_arr과 arr은 서로 다른 변수이기 때문에 re_arr 값을 변경해도 arr 값은 변경되지 않습니다. 메모리 재할당을 위해서는 pointer of pointer를 인자로 받아야 합니다.
아래 코드는 심심해서 작성해 본 것 입니다.
template<T> T* resize(T** t,int size)
{
  T* tmp = new T[size];
  memcpy(tmp,*t,sizeof(T)*size);
  *t = tmp;
  return tmp;
}

질문자께서 작성하신 첫 프로그램은 일단 다른 분 들 께서 지적해 주신 대로 문제가 많습니다. 인자값이 제대로 넘어오지 않았고, return을 하지 않으면서 return을 받고, 새로 잡힌 메모리를 return으로 받아오고 싶은 건지, 인자로 넣은 상태에서 변경하고 싶은 것인 지 모호합니다.

인자로 넘긴 포인터를 바꾸고 싶은 거라면 윗 분께서 작성하신 것 처럼 pointer of pointer나 reference of pointer를 쓰시는 것이 맞고.. 좀 더 C++ oriented하게 생각하신다면 vector를 써서 vector::resize()를 쓰시는 것이 현명한 선택이겠죠.. 싱글 포인터를 넘기고 리턴으로 다시 값을 받아와야 하는 구조는 별로 좋아 보이지 않습니다.

tinywolf의 이미지

이 코드 상당히 흥미를 유발시키는 군요..

char *resize(char *, int a);
int main(){

   char *arr= new char[10];

   arr= resize(arr, 100);

   // 재조정된 배열 사용..

   delete[] arr;

   return 0;
}

char *resize(char *re_arr, int a){

   delete[] re_arr;
   return (new char[a]);
}

혹은..
bool resize(char* &re_arr, int a);
int main(){

   char *arr= new char[10];

   resize(arr, 100);

   // 재조정된 배열 사용..

   delete[] arr;

   return 0;
}

bool resize(char* &re_arr, int a){

   delete[] re_arr;
   re_arr = new char[a];

   return true;
}

조그만게 생각하는 재미가 있군요..
(컴파일 확인은 안해봤습니다~ ^^; )

코드 놀이터로 원츄b

ㅡ_ㅡ;

singlet의 이미지

이리저리 고쳐보시는 분들이 몇 분 계신데요. 제 의견으로는
char *resize(char *buf, size_t size);
라는 인터페이스 내지는 이와 유사한 것들을 사용하는 한, 애초에 제대로 돌아갈 리가 없을 거라고 봅니다. 이하 제 생각을 적어보겠습니다.

new[] / delete[] 를 이용하여 작성한 resize() 는, 구현 세부사항을 컨닝하거나 전역 new / delete 를 재작성하는 극약처방을 하지 않는 이상 블럭 자체를 재할당할 수가 없습니다. 정상적으로 할 수 있는 것은 할당-복사-해제의 3단계를 거치는 정도지요. 따라서 이 함수의 핵심은 대략 다음과 같아질 겁니다.

char *resize(char *buf, size_t size)
{
  char *tmp = new char[size];
  for (size_t i = 0; i < size; ++i)
    tmp[i] = buf[i];
  delete[] buf;
  return tmp;
}

그런데, 문제는 tmp 가 buf 보다 더 클 경우에 발생합니다. 이 경우 접근해서는 안 되는 원소에 접근하게 되니까요. 예를 들어 다음 코드
char *p = new char[10];
p = resize(p, 1024 * 1024);
delete[] p;

는 제 머신에서 buf[135160] 에 접근하려다가 죽어버리더군요. 이 문제를 해결하려면 저 for 루프에서 '기 할당된 배열의 크기' 와 size 사이에서 더 작은 값을 취해야 할 겁니다만, 정상적으로 작성한 resize() 함수가 '기 할당된 배열의 크기'를 알아낼 수 있는 방법은 없으므로 제대로 동작할 수도 없습니다.
happycat의 이미지

원 코드는 원본 보장이 되지 않고 글 타래 중에 한 번 지적이 되었습니다. :) 설마 질문자께서 원본 보존 resize를 생각하고 짜신 거였다면.. 대략 낭패;;

singlet의 이미지

happycat wrote:
원 코드는 원본 보장이 되지 않고 글 타래 중에 한 번 지적이 되었습니다. :) 설마 질문자께서 원본 보존 resize를 생각하고 짜신 거였다면.. 대략 낭패;;

원본을 보존할 이유가 없다면 vector::resize() 를 쓰라는 조언도 무의미죠. 설마 원본을 보존하지 않는 resize() 를 원하셔서 저리 짜신 건 아닐 거라고 추정했습니다. :)

개인적인 의견으로는, 원본을 보존하지 않는 함수를 원하신 게 정녕 사실이라면 그냥 함수 작성하지 말고 직접 delete[] / new[] 하는 쪽이 명확합니다. 개념상 이건 배열을 resize하는 것이 아니라 아예 다른 배열을 이용하려는 것이니까요.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.