C++의 전체 복사 VS 얕은 복사

Jinku Hu 2023년10월12일
  1. 얕은 복사는 C++의 기본 복사 생성자에서 사용됩니다
  2. 사용자 지정 복사 생성자를 사용하여 C++에서 전체 복사 동작 구현
C++의 전체 복사 VS 얕은 복사

이 기사에서는 C++에서 딥 복사 VS 얕은 복사를 사용하는 방법에 대한 여러 방법을 보여줍니다.

얕은 복사는 C++의 기본 복사 생성자에서 사용됩니다

C++ 클래스는 일반적으로 사용자가 명시 적으로 지정하거나 컴파일러에 의해 암시 적으로 지정된복사 제어라고하는 여러 작업으로 정의됩니다. 이러한 멤버 함수는복사 생성자,복사 할당 연산자,이동 생성자,이동 할당 연산자소멸자로 표시됩니다. 복사 생성자 및 이동 생성자는 객체가 동일한 유형의 다른 객체에서 초기화 될 때 발생하는 작업을 구현합니다. 그러나 이러한 함수가 컴파일러에 의해 암시 적으로 합성되면 일부 클래스 유형이 잘못 작동 할 수 있습니다. 예를 들어 동적 메모리를 관리하는 클래스는 수동으로 할당해야하는 데이터 멤버를 공유합니다. 따라서 프로그래머는 위의 멤버 함수를 명시 적으로 구현할 책임이 있습니다.

이 경우,new연산자를 사용하여 할당 된 두 개의std::string데이터 멤버가있는Person클래스의 복사 생성자의 경우를 보여줍니다. 다음 예제 코드는 복사 생성자가 명시 적으로 정의되지 않고Person객체를 다른Person객체로 초기화 할 때 발생하는 일을 보여줍니다. P1에는 초기화 후Buddy/Rich문자열이 저장되어 있고P2는 명령문에서 복사 생성자가 호출 된 후Person P2 = P1;과 동일한 값을가집니다. P1개체에서renamePerson기능이 실행 된 후P2개체의surname데이터 멤버도 수정됩니다.

#include <iostream>
#include <string>
#include <utility>
#include <vector>

using std::cout;
using std::endl;
using std::string;
using std::vector;

class Person {
 public:
  Person() = default;
  Person(string n, string s) {
    name = std::move(n);
    surname = new string(std::move(s));
  }

  ~Person() { delete surname; }

  void renamePerson(const string &n, const string &s) {
    name.assign(n);
    surname->assign(s);
  };

  string &getName() { return name; };
  string &getSurname() { return *surname; };

  void printPerson() { cout << name << " " << *surname; }

 private:
  string name;
  string *surname{};
};

int main() {
  Person P1("Buddy", "Rich");
  Person P2 = P1;

  P1.printPerson();
  cout << endl;
  P2.printPerson();
  cout << endl;

  P1.renamePerson("Heinz", "Lulu");

  P1.printPerson();
  cout << endl;
  P2.printPerson();
  cout << endl;

  exit(EXIT_SUCCESS);
}

출력:

Buddy Rich
Buddy Rich
Heinz Lulu
Buddy Lulu

사용자 지정 복사 생성자를 사용하여 C++에서 전체 복사 동작 구현

반면에Person클래스에 대한 사용자 정의 복사 생성자를 구현하면 올바르게 작동하고P1.renamePerson("Heinz", "Lulu")문 다음에P2개체를 수정하지 않습니다. 이전 코드 스 니펫에서P2오브젝트의surname멤버는P1오브젝트와 동일한 문자열을 가리키고renamePerson이 두 오브젝트를 수정했습니다. 이번에P2는 동적 메모리에 할당 된 고유 한surname멤버를 가지며P1오브젝트와 공유하지 않습니다.

#include <iostream>
#include <string>
#include <utility>
#include <vector>

using std::cout;
using std::endl;
using std::string;
using std::vector;

class Person {
 public:
  Person() = default;
  Person(string n, string s) {
    name = std::move(n);
    surname = new string(std::move(s));
  }
  Person(Person &p) {
    name = p.name;
    surname = new string(*p.surname);
  }

  ~Person() { delete surname; }

  void renamePerson(const string &n, const string &s) {
    name.assign(n);
    surname->assign(s);
  };

  string &getName() { return name; };
  string &getSurname() { return *surname; };

  void printPerson() { cout << name << " " << *surname; }

 private:
  string name;
  string *surname{};
};

int main() {
  Person P1("Buddy", "Rich");
  Person P2 = P1;

  P1.printPerson();
  cout << endl;
  P2.printPerson();
  cout << endl;

  P1.renamePerson("Heinz", "Lulu");

  P1.printPerson();
  cout << endl;
  P2.printPerson();
  cout << endl;

  exit(EXIT_SUCCESS);
}

출력:

Buddy Rich
Buddy Rich
Heinz Lulu
Buddy Rich
작가: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

관련 문장 - C++ Class