2014-02-16 3 views
2

정수 집합을 나타내는 클래스를 코딩하려고합니다. 숙제가 있지만 나에게있어서이 문제를 이해할 수는 없습니다.C++ : 포인터가 가리키는 값이 변경됩니다.

"IntSet"클래스에는 두 개의 전용 변수가 있습니다. 하나는 배열에 대한 포인터이고 다른 하나는 배열의 크기입니다. 이 클래스의 객체를 만들 수 있으며 의도 한대로 작동합니다. 하지만 IntSet 클래스의 개체를 반환하는 "조인"이라는이 함수가 있습니다. 그것은 기본적으로 배열을 연결 한 다음 해당 배열을 사용하여 반환하는 객체를 만듭니다. 여기

내 코드입니다 :

#include <iostream> 
using namespace std; 

class IntSet { 
     int * arrPtr; 
     int arrSize; 
    public: 
     //Default Constructor 
     IntSet() { 
      int arr[0]; 
      arrPtr = arr; 
      arrSize = 0; 
     } 
     //Overloaded Constructor 
     IntSet(int arr[], int size) { 
      arrPtr = arr; 
      arrSize = size; 
     } 

     //Copy Constructor 
     IntSet(const IntSet &i) { 
      arrPtr = i.arrPtr; 
      arrSize = i.arrSize; 
     } 

     /* 
     * Returns a pointer to the first 
     * element in the array 
     */ 
     int* getArr() { 
      return arrPtr; 
     } 

     int getSize() { 
      return arrSize; 
     } 

     IntSet join(IntSet &setAdd) { 

      //Make a new array 
      int temp[arrSize + setAdd.getSize()]; 

      //Add the the values from the current instance's array pointer 
      //to the beginning of the temp array 
      for (int i = 0; i < arrSize; i++) { 
       temp[i] = *(arrPtr + i); 
      } 

      //Add the values from the passed in object's array pointer 
      //to the temp array but after the previously added values 
      for (int i = 0; i < setAdd.getSize(); i++) { 
       temp[i + arrSize] = *(setAdd.getArr() + i); 
      } 

      //Create a new instance that takes the temp array pointer and the 
      //size of the temp array 
      IntSet i(temp, arrSize + setAdd.getSize()); 

      //Showing that the instance before it passes works as expected 
      cout << "In join function:" << endl; 
      for (int j = 0; j < i.getSize(); j++) { 
       cout << *(i.getArr() + j) << endl; 
      } 

      //Return the object 
      return i; 
     } 

}; 

int main() { 

    //Make two arrays 
    int arr1[2] = {2 ,4}; 
    int arr2[3] = {5, 2, 7}; 

    //Make two objects normally 
    IntSet i(arr1, 2); 
    IntSet j(arr2, 3); 


    //This object has an "array" that has arr1 and arr2 concatenated, essentially 
    //I use the copy constructor here but the issue still occurs if I instead use 
    //Inset k = i.join(j); 
    IntSet k(i.join(j)); 

    //Shows the error. It is not the same values as it was before it was returned 
    cout << "In main function:" << endl; 

    for (int l = 0; l < k.getSize(); l++) { 
     cout << *(k.getArr() + l) << endl; 
    } 

    return 0; 
} 

이 프로그램은 컴파일하고 지금과 같은 출력은 다음과 같습니다

In join function: 
2 
4 
5 
2 
7 
In main function: 
10 
0 
-2020743083 
32737 
-2017308032 

나는 이유는 모르겠지만, 10, 0마다 항상 동일 다시 컴파일하고 실행할 시간. 또한 포인터의 주소가 아니라 조인 함수와 주 함수에서 값을 인쇄 할 경우, 같은 메모리 주소를 가져옵니다.

죄송합니다. 용어를 오용하면 자바 배경에서 왔으므로 포인터와 같은 것이 나에게 조금 새로운 것입니다. 설명이 필요하면 질문하십시오.

미리 감사드립니다.

+1

생성자에서 로컬 변수를 선언하고 포인터를 유지하면 좋지 않을 수 있습니다. – codah

답변

4
int temp[arrSize + setAdd.getSize()]; 

이것은 로컬 배열이며 함수가 반환되면 수명이 끝납니다.

IntSet i(temp, arrSize + setAdd.getSize()); 

여기서이 배열로 IntSet을 구성합니다. 사실 생성자는 단순히 temp의 값 멤버 포인터 변경 : temp 결과적으로는 i.arrPtrjoin을 떠난 후 끝을 가리키고있는 개체의 수명 때문에, 결과적으로

IntSet(int arr[], int size) { 
    arrPtr = arr; 
    arrSize = size; 
} 

을, 당신은있을 것이다 와일드 포인터. 나중에 main에서이 포인터를 역 참조하면 정의되지 않은 동작이 호출됩니다.

new[]으로 배열을 동적으로 할당하고 나중에 delete[]으로 삭제해야합니다. 생성자도 마찬가지입니다. 또한 소멸자에서 joindelete[]new[]을 사용하는 경우 복사 생성자가 실제로 배열을 복사하는지 확인해야합니다 (new[] 및 복사 내용으로 새 배열 만들기). 간단하게 포인터를 할당하면 소스와 대상 객체가 같은 배열을 가리키며 해체 될 때 모두 삭제하려고 시도하고 다시 정의되지 않은 동작을 호출합니다.

그러나이 C++ 이후로이 모든 작업을 수행하는 std::vector을 사용할 수도 있습니다.

+0

임시 변수의 범위를 완전히 간과했습니다. 동적으로 할당 된 'new'로 변경 한 후 작동했습니다. 고마워요. @ 윌렘. – xadeka

+0

+1, 그리고 보너스로, 세 가지 (vector, set 및'std :: set_intersection '과 같은 표준 알고리즘을 모두 사용하여 [이것을 수행하는 한 가지 방법] (http://ideone.com/bQ3Yu8) OP 학부모가 조사하기에 합당한 지 알기 쉽습니다. – WhozCraig

0

코드와 가장 빠른 수정이

int * temp = new int[arrSize + setAdd.getSize()]; 

건에

int temp[arrSize + setAdd.getSize()]; 

을 변경하는 것입니다 (실제로 정수 세트를 원하는 경우 또는 std::set)를 사용하면 스택에 임시 할당한다는 것입니다 , 그래서 join()이 release 메모리를 반환 할 때. 힙에 메모리를 할당하면 (수정 사항에 따라) join()이 반환 될 때 메모리가 해제되지 않습니다.

코드에 다른 문제가 있습니다 (할당 시점에 따라 다름). 난 당신이 힙에 메모리를 가지고 의미를 고려하면 대부분의 고정 될 것이라고 생각합니다.

관련 문제