[완료] (다시질문) 배열의 내용이 변경되지 않게 하려면..

hugeval의 이미지

며칠 전 드린 질문과 같은건데요

class ARRAY
{
public:
int arr1[100];
int* arr2;

ARRAY(){
arr2=NULL;
arr2 = new int[100];
};
~ARRAY(){
if( arr2 ) delete[] arr2;
};
void a1() { arr1[0] = 10; };
void a2() { arr2[0] = 10; };
};

void func(const ARRAY* Array)
{
Array->arr1[0] = 10; // 1 에러
Array->a1(); // 2 에러

Array->arr2[0] = 10; // 3 정상
Array->a2(); // 4 에러
}

int _tmain(int argc, _TCHAR* argv[])
{
ARRAY Array;
func(&Array);
return 0;
}

arr2는 동적할당한 배열입니다
위에 func 보시면 1,2,4는 예상대로 에러 납니다
근데 3에서는 문제가 없더군여
arr2가 동적할당한 배열이라서 그런건가요?
왜 3에서는 에러가 안나는건지를 알고싶습니다ㅠ

cdecl의 이미지

우선 1번과 2번이 에러가 나는 이유가 틀린 부분을 이해를 하셔야 할듯합니다.

1번은 const ARRAY* Array 가 const 인스턴스 이므로 멤버에 대해서 수정 불가 에러..
2번은 a1() 함수가 const 한정자가 붙은 버전의 함수가 없으므로 컴파일 에러가 발생한 것입니다.
2번을 애초 의도(?) 대로 멤버에 대한 수정 불가 에러를 발생 시키시려면 a1() 함수에 대해서 const 한정자를 붙이셔야 합니다.

void a1() const { arr1[0] = 10; };

이렇게 하면 비로서 멤버에 대해서 수정 불가 에러는 발생 합니다.

4번의 경우도 위의 2번의 경우와 같이 적용 되는것이고,
3번의 경우 에러가 안나는 이유는 포인터변수의 자체값, 그러니까 주소값을 변경 한것이 아니고
그 주소가 가르키고 있는 값을 변경을 했기 때문에 문제가 없는것입니다.

만약 Array->arr2 = NULL; 하셨다면 원하시는 에러는 발생 시켰을 것입니다.

위의 결과대로 4번의 경우도 const 버전의 함수가 제공된다면 에러를 발생하지 않습니다.

void a2() const { arr2[0] = 10; };

Array->a2(); // 4 성공..

--
cdecl

--
cdecl

netionics의 이미지

을 이해해야합니다. 추가로 객체가 const로 선언되었을 때 멤버에 적용되는 규칙을 알아보세요.

:)

hugeval의 이미지

일단 답변 감사합니다^^

1번과2번이 다른이유로 에러가 발생한거였군요.

근데 const ARRAY* Array는 Array가 가리키는
객체의 내용을 변경할수없는것인데
멤버포인터 arr2가 가리키는 동적할당한 배열의 내용도 변경이 안되야할텐데
왜 에러가 안나는지가 궁금한거거든요
3번은 arr2의 주소값을 변경하려는게아니라
1번과 똑같이 배열요소를 변경하는거거든요.

그래서 정적할당한 배열과 동적할당한 배열이라는 차이점때문에
에러가 나고 안나는건가 궁금했습니다.

hugeval의 이미지

첫번째는 p가 가리키는 객체의 내용을 변경할수없는것이고 다른객체를 가리킬순있습니다
두번째는 p의 주소값을 변경할수없기때문에 다른객체를 가리킬수없다는걸로 알고있습니다
대신 가리키는 객체의 내용은 변경할수있습니다
아닌가요?

netionics의 이미지

const 로 객체를 한정했을 때
멤버가 배열이면 배열 요소 하나 하나가 const로 한정되는 효과르 갖습니다.
포인터라면 포인터만 한정되죠. 즉 char* const arr2와 같아집니다.

기본복사생성자도 멤버가 배열이면 배열의 요소 하나하나를 다 복사해주는 등, 배열에 대해 특별한 처리를 해주는 경우가 있습니다.

class something {
public:
    something(int val) { std::fill(arr, arr+100, val); }
    int arr[100];
};
 
something a(1), b(2);
a = b; // 굳이 복사생성자를 만들지 않아도 a.arr[0..100]은 모두 2가 됩니다.

:)

hugeval의 이미지


멤버변수가 포인터인경우에는 포인터변수만 해당하는거군요~

그렇다면 멤버포인터가 가리키고있는 배열까지도 변경되지 않게 할수는 없나요?ㅋ

klyx의 이미지

std::vector를 이용하세요.

hugeval의 이미지


첨에 vector 썼다가 디버깅이 어려워서
int 배열쓰는건데요
흠.. 좀더 고민을 해봐야겠습니다
답변 감사합니다!

댓글 달기

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