2012-08-23 4 views
5

복사 생성자는 포인터를 사용해야하거나 객체에 동적으로 메모리를 할당해야하는 경우와 같이 많은 경우에 사용됩니다.복사 생성자 예제 설명

#include <iostream> 

using namespace std; 

class Line 
{ 
public: 
    int getLength(void); 
    Line(int len);    // simple constructor 
    Line(const Line &obj); // copy constructor 
    ~Line();      // destructor 

private: 
    int *ptr; 
}; 

// Member functions definitions including constructor 
Line::Line(int len) 
{ 
cout << "Normal constructor allocating ptr" << endl; 
// allocate memory for the pointer; 
ptr = new int; 
*ptr = len; 
} 

Line::Line(const Line &obj) 
{ 
cout << "Copy constructor allocating ptr." << endl; 
ptr = new int; 
*ptr = *obj.ptr; // copy the value 
} 

Line::~Line(void) 
{ 
cout << "Freeing memory!" << endl; 
delete ptr; 
} 
int Line::getLength(void) 
{ 
return *ptr; 
} 

void display(Line obj) 
{ 
    cout << "Length of line : " << obj.getLength() <<endl; 
} 

// Main function for the program 
int main() 
{ 
    Line line(10); 

    display(line); 

    return 0; 
} 

결과는 다음과 같습니다 : 그러나 tutorialpoint.com에서이 예를보고

Normal constructor allocating ptr 
Copy constructor allocating ptr. 
Length of line : 10 
Freeing memory! 
Freeing memory! 

내가 (복사 생성자)와 소멸자 내부의 코드를 주석 때이 같은 결과를 얻었다 :

Normal constructor allocating ptr 
Length of line : 10 

여기에 복사 생성자를 사용하는 것과 다른 점은 무엇입니까? 또한 왜 "Freeing Memory!" 두 번 나타 납니까?

+2

결과를 살펴보십시오. 첫 번째 예제에서는 두 개의 서로 다른 int를 할당하고 둘 다 해제합니다. 두 번째 단계에서는 하나를 할당하고 두 번 해방하십시오. 안좋다. – chris

+0

두 번째 예제에서 해제되지 않은, 나는 방금 "cout <<"메모리를 해제 주석을 깜빡!"문을 생성자 내부에서 처리하므로 실제로 해제되지 않았습니다. – Omar

+0

그런 다음 해제하지 않은 내용을 할당 했으므로 프로그램을 끝내고 프로그램을 종료하는 것보다 복잡해지기 시작하면 메모리 누수가 발생합니다. – chris

답변

3

display() 함수의 인수는 값에 의해 전달되므로 컴파일러는 복사 생성자를 호출하여 복사 생성자를 호출합니다. 클래스가 복사 생성자를 정의 할 때 올바른 의미를 얻습니다. 복사 생성자가 복사를 만들고 그 사본에는 길이를 보유 할 자체 메모리가 있습니다. 복사 생성자를 제거하면 컴파일러에서 자동으로 생성하고 display()에 전달 된 복사본은 원본과 동일한 포인터를 갖습니다. 그 사본이 파괴되면 ptr이 가리키는 메모리를 삭제합니다. 원본이 파괴되면 동일한 메모리가 다시 삭제됩니다 (여기서 보이는 효과는 없습니다). 그건 분명히 당신이 원하는 일이 아니기 때문에 복사 생성자를 정의해야합니다. @Joe는 다음과 같이 말합니다 : 소멸자 내에서 이것을 더 명확하게 보려면`ptr '의 값을 출력하십시오.

4

해제 할 메모리의 주소를 인쇄하십시오.

나는 컴파일러가 생성자를 생성하고 포인터를 포함한 내용의 값 복사본을 생성했다는 것을 알게 될 것이며 포인터를 두 번 풀어서 런타임이 그것에 대해 불평하지 않는다고 운좋게 느낀다고 생각한다. .

컴파일러에서 생성 된 복사본 생성자가 여전히 호출되고 있습니다. 그 점에서 변경된 사항은 없습니다. 작성하지 않았으므로 아무 것도 인쇄하지 않습니다.

0

단일 인수가 동일한 유형 의 기존 객체에 const를 참조해야합니다

T (const & T); 

형태의 일부 타입 T의 생성자는 사용 기존 개체 의 복제본을 생성 할 때마다의 사본 객체가 필요함 함수에 대한 인수 포함, 함수에서 반환 된 결과 C++에서 포인터 기반 배열의 문제 : - 범위 검사가 없습니다. == 배열을 할당 할 수 없습니다 (배열 이름은 const 포인터 임). 배열이 함수에 전달되면 size는 별도의 인수로 전달되어야합니다.

1

우리가 자체 복사 생성자를 정의하지 않으면 C++ 컴파일러는 각 클래스에 대해 개체 사이에 구성원 별 복사본을 만드는 기본 복사 생성자를 만듭니다. 컴파일러는 일반적으로 잘 작동하는 복사 생성자를 만들었습니다. 객체에 포인터가 있거나 파일 핸들, 네트워크 연결과 같은 리소스의 런타임 할당이있는 경우에만 복사 생성자를 정의해야합니다.