c++의 얕은 복사와 깊은 복사

4485 단어
복사 구조 함수는 기본적인 C++ 프로그래밍에 그다지 쓸모가 없을 수도 있지만 이것은 복사 구조 함수가 쓸모가 없다는 것을 설명하지 않고 우리가 흔히 소홀히 하는 문제를 해결할 수 있다.
현재 Student 클래스가 있고 데이터 구성원 중 하나가char*name이라고 가정합니다.
현재 대상인 Student stu1("yang")이 있습니다.//데이터 구성원name="yang";
하나의 대상을 생성하여stu2,stu1을stu2,즉studentstu2(stu1)에 복사한다.
만약 우리가 직접 복사 구조 함수를 쓰지 않는다면 컴파일러는 기본 복사 구조 함수를 호출하여 얕은 복사를 할 것이다.
얕은 복사란 메모리 공간에'yang'이 하나밖에 없다는 뜻이다. 대상stu1의name 바늘이 그것을 가리키고 stu1을stu2에 복사한다. stu2의name도 그 메모리 공간을 가리키고 stu1과stu2는 하나의 메모리 공간을 공유한다. 그러면 문제가 발생한다. stu1의 대상이 소각되면 대응하는stu1의name가가리키는'yang'페이지가 소각된다. 그러나stu2도 그것을 가리키기 때문에 stu2는 비어 있고 심지어 난코드가 된다.  
다음 예를 참조하십시오.
#include<iostream>
using namespace std;
class Array{
public:
    int size;
    int *data;
    Array(int size):size(size),data(new int[size]){}
    ~Array(){
        delete[] this->data;
    }
};
int main(int argc,char *argv[])
{
    Array first(20);
    first.data[0]=25;
    {
        Array copy=first;
        cout << first.data[0] << " "<<copy.data[0] << endl;
    }(1)

    first.data[0]=10;(2)
    return 0;
}

실행 결과:
25 25
*** Error in `./a.out': double free or corruption (fasttop): 0x0000000001821010 ***
  ( )

왜 우리가 가장 골치 아픈 단락의 오류가 나타날까요?


근본 원인은 앞의 어느 예와 마찬가지로 우리는 카피 구조 함수를 쓰지 않았기 때문에 컴파일러는 기본 카피 구조 함수를 생성하고 기본 카피 구조 함수는 다음과 같다.
Array(const Array& other)  
  : size(other.size), data(other.data) {}  

데이터 포인터에 대한 간단한 복사입니다. 즉, 데이터 구성원의 주소만 복사했기 때문에 두 포인터 공유 대상이 같은 메모리를 가리키는 위험을 가져왔습니다. 
프로그램이 (1)에 실행되었을 때,copy의 분석 함수가 호출되어,copy의 데이터를 삭제합니다.first와copy 대상이 데이터 바늘을 공유하기 때문에 (2)에 실행되었을 때, 메모리 공간이 방출되어 발생한 단락 오류
그래서 반드시 스스로 카피 구조 함수를 쓰고 깊은 카피를 실행해야 한다.
Array(const Array& other)  
    : size(other.size), data(new int[other.size])   
{  
    std::copy(other.data, other.data + other.size, data);   
}  

얕은 복사와 깊은 복사는 무엇입니까?


간단한 복사: 자원을 복사하지 않고 한 명씩 복사하는 방식;얕은 복사란 원본 대상과 복사 대상이 공용하는 실체를 가리키며 인용하는 변수만 다르다(이름이 다르다).그 중 어느 대상에 대한 변경도 다른 대상에게 영향을 미칠 수 있다. 비교적 전형적인 것은 Reference(인용) 대상, 예를 들어Class(클래스)가 있다.
딥 카피: 구성원을 카피하고 자원을 카피하는 방식.심층 복사란 원본 대상과 복사 대상이 서로 독립되어 그 중 어떤 대상의 변경도 다른 대상에게 영향을 주지 않는다는 것을 말한다.비교적 전형적인 것은 바로 Value(값) 대상이다. 예를 들어 미리 정의된 유형인 Int32, Double, 그리고 구조(struct), 매거(Enum) 등이다.
시스템이 제공하는 기본 복사 구조 함수는 얕은 복사이며, 깊은 복사는 반드시 스스로 정의해야 한다.
이것 또한 상단 코드의 중단 오류 원인과 왜 스스로 복사 구조 함수를 써야 하는지를 설명했다.

무엇이 복사 구조 함수입니까?


복사 구조 함수는 특수한 구조 함수로 컴파일러가 호출하여 같은 종류의 다른 대상을 바탕으로 하는 구축과 초기화를 완성한다.유일한 매개 변수 (대상의 인용) 는 변할 수 없습니다. (const 형식)즉, 이미 존재하는 대상을 새로운 대상으로 값을 부여할 때 먼저 새로운 대상의 데이터 구성원에게 공간 자원을 분배하여 새로운 대상을 만들고 원본 대상의 구성원 값으로 초기화해야 한다.이 행위는 반드시 대상을 구성할 때 완성해야 하는데 일반적인 구조 함수는 이 작업을 완성할 수 없기 때문에 복사 구조 함수는 운명적으로 생겨난다!
C++에서 다음 세 가지 대상을 복사해야 하는 경우.따라서 복사 구조 함수는 호출될 것이다.1). 한 대상이 값을 전달하는 방식으로 함수체 2를 전달한다. 한 대상이 값을 전달하는 방식으로 함수에서 3을 되돌려준다. 한 대상이 다른 대상을 통해 초기화되어야 할 때.이상의 경우 구조 함수를 복사하여 호출해야 한다.만약 앞의 두 가지 상황에서 복사 구조 함수를 사용하지 않을 때, 바늘이 삭제된 메모리 공간을 가리키게 될 것이다.세 번째 상황에서 초기화와 부수의 다른 의미는 구조 함수 호출의 원인이다.사실상 복사 구조 함수는 일반 구조 함수와 부수 조작부가 공동으로 실현한 것이다.

요약:


1) 복사 구조 함수의 역할은 대상을 복제하는 데 사용되며, 이 대상의 실례를 사용하여 이 대상의 새로운 실례를 초기화하는 것이다.2) 만약에 명시적으로 구조 함수를 복사하지 않을 때 컴파일러도 기본적인 복사 구조 함수를 생성하고 얕은 복사만 실행하면 일반적인 상황에서도 얕은 복사가 잘 실행된다.
그러나 클래스에 포인터 데이터 구성원이 있을 때 문제가 발생했다. 기본적인 복사 구조 함수는 구성원에 따라 복사 구조이기 때문에 두 개의 서로 다른 포인터(예를 들어 ptr1=ptr2)가 같은 메모리를 가리키게 되었다.하나의 실례가 소각될 때 분석 함수free(ptr1)를 호출하여 이 메모리를 방출하면 나머지 실례의 바늘인 ptr2는 무효가 되고 소각될 때free(ptr2)는 오류가 발생합니다. 이것은 하나의 메모리를 두 번 반복해서 방출하는 것과 같습니다.이런 상황은 새로운 실례의 지침에 새로운 메모리를 분배하기 위해 자신의 복사 구조 함수를 현시적으로 설명하고 실현해야 한다.

좋은 웹페이지 즐겨찾기