2015-01-24 3 views
2

빠른 진행 C++ 수정 과정을 진행 중입니다. 몇 가지 기본 개념을 닦으려고. 아래 프로그램을 실행하면 두 가지 문제가 발생합니다. 1. 복사 CC가 어떤 이유로 호출되지 않습니다. 2. testCC() 함수가 종료 된 후 프로그램이 작동하지 않습니다.복사 생성자가 여기에서 호출되지 않는 이유는 무엇입니까?

도움을 주시면 감사하겠습니다.

class A 
{ 
public: 
    A() 
    { 
     this->ptr = new int[10]; 
    } 
    ~A() 
    { 
     delete[] ptr; 
    } 
    A(const A &obj) 
    { 
     std::cout << "Copy CC called\n"; 
     for (int i = 0; i < 10; i++) 
     { 
      ptr[i] = obj.ptr[i]; 
     } 
    } 
    void set() 
    { 
     for (int i = 0; i < 10; i++) 
     { 
      ptr[i] = rand() % 10; 
     } 
    } 
    void print() 
    { 
     for (int i = 0; i < 10; i++) 
     { 
      std::cout << ptr[i] << " "; 
     } 
     std::cout << "\n"; 
    } 
private: 
    int *ptr; 

}; 

void testCC() 
{ 
    A a1,a2; 
    a1.set(); 
    std::cout << "Contents of a1\n"; 
    a1.print(); 
    a2 = a1; 
    std::cout << "Contents of a2\n"; 
    a2.print(); 
} 
+0

또한 [this] (http://en.wikipedia.org/wiki/Rule_of_three_%28C%2B%2B_programming%29) – P0W

답변

1
a2 = a1; 

은 복사 할 과제이다.

A a3 = a1; 

복사 생성자를 호출합니다.

은 같은 것이 아니다 이것은

a2 = a1; 
+0

@MattMcNabb가 업데이트되었습니다. OP의 cctor를 복사하고 변경하려고 계획했지만 잊어 버렸습니다. – user93353

4

복사 할당 및 복사 건설에 의해 호출됩니다

A & operator=(const A & obj) 
{ 
    std::cout << "Assingment called\n"; 
    for (int i = 0; i < 10; i++) 
    { 
     ptr[i] = obj.ptr[i]; 
    } 

    return *this; 
} 

할당 연산자를 작성합니다.

a2 = a1은 복사 생성자가 아닌 a2.operator=(a1) (복사본 할당)입니다. 당신의 복사 생성자가 있었다 그래서 경우에도 (당신이 그것을 사용하기 전에 ptr를 초기화하지 않음) 귀하의 복사 생성자가 불량,

A & operator=(A const & obj) 
{ 
    // Perform copy... 

    return *this; 
} 

그리고 어느 쪽이든 : 당신은 A 클래스 내에서이 같은 복사 할당 연산자를 정의 할 수 있습니다 사용중인 경우 정의되지 않은 동작이 호출되어 충돌 할 수 있습니다. 내가 믿는

+0

왜 OP에서 충돌이 발생하는지 언급해야합니다. 마지막 행은이 충돌의 원인이 아닙니다. – P0W

+1

이것에 더하여, [copy and swap idiom] (http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom)을 사용하여 할당 연산자를 구현하는 것이 좋습니다 . –

4

문제는이 라인 :

a2 = a1; 

A2가 이미 존재하기 때문에이 라인은 A의 복사 생성자를 호출하지 않습니다. A& operator=(const A&)

할당 연산자를 정의하지 않았으므로 기본 컴파일러에서 비트 복사를 생성합니다. (이 시점에서 생성되지 않습니다. 결과적으로 a2와 a1은 모두 같은 ptr 값을 포함하고 있습니다. 이것이 프로그램이 충돌하는 이유입니다. testCC이 종료되면 a1과 a2가 모두 삭제되고 동일한 배열이 해제됩니다.

+0

크래시를 설명해 주셔서 감사합니다 +1 – P0W

+0

설명을 주셔서 감사합니다. – vinit

2

a2 = a1은 복사 생성자가 아니라 복사 할당 연산자를 호출합니다. 클래스는 복사 할당 연산자를 구현하지 않으므로 컴파일러는 구성원 별 복사 만 수행하는 기본 연산자를 생성합니다. a1 = a2 이후에 동일한 메모리를 가리키는 ptr의 사본이 두 개 있습니다. ab은 모두 testCC이 반환 할 때 삭제하려고합니다. 이 이중 삭제로 인해 충돌이 발생합니다.

당신은 생성자이고 객체를 생성하고 A2가 이미 생성되는 동안 호출해야하기 때문에 복사 생성자를 호출하지 않습니다

0

A a2(a1) 또는 A a2 = a1를 작성하여 복사 생성자를 테스트 할 수 있습니다.

크래시의 가능한 원인은 testCC 이후에 소멸자가 호출되면 a1의 소멸자가 포인터를 해제하지만 a2의 포인터도 소멸자에서 삭제하는 동안 동일한 위치를 가리키고 있기 때문에 충돌 할 수 있습니다.

아무 것도 복사하기 전에 항상 개체를 구성하십시오.

관련 문제