수색…


깊은 복사 및 이동 지원

유형이 값 의미론을 가지기를 원하고 동적으로 할당 된 객체를 저장해야하는 경우 복사 작업에서 유형은 해당 객체의 새 복사본을 할당해야합니다. 또한 사본 할당을 위해이 작업을 수행해야합니다.

이런 종류의 복사를 "딥 카피"라고합니다. 그것은 실제로 다른 경우라면 참조 의미론을 가져 와서 값 의미 화로 바꾼다.

struct Inner {int i;};

const int NUM_INNER = 5;
class Value
{
private:
  Inner *array_; //Normally has reference semantics.

public:
  Value() : array_(new Inner[NUM_INNER]){}

  ~Value() {delete[] array_;}

  Value(const Value &val) : array_(new Inner[NUM_INNER])
  {
    for(int i = 0; i < NUM_INNER; ++i)
      array_[i] = val.array_[i];
  }

  Value &operator=(const Value &val)
  {
    for(int i = 0; i < NUM_INNER; ++i)
      array_[i] = val.array_[i];
    return *this;
  }
};
C ++ 11

Move semantics는 Value 와 같은 유형을 허용하여 참조 된 데이터를 실제로 복사하지 않도록합니다. 사용자가 이동을 유발하는 방식으로 값을 사용하면 객체의 "copied"는 참조 된 데이터가 비어있게됩니다.

struct Inner {int i;};

constexpr auto NUM_INNER = 5;
class Value
{
private:
  Inner *array_; //Normally has reference semantics.

public:
  Value() : array_(new Inner[NUM_INNER]){}

  //OK to delete even if nullptr
  ~Value() {delete[] array_;}

  Value(const Value &val) : array_(new Inner[NUM_INNER])
  {
    for(int i = 0; i < NUM_INNER; ++i)
      array_[i] = val.array_[i];
  }

  Value &operator=(const Value &val)
  {
    for(int i = 0; i < NUM_INNER; ++i)
      array_[i] = val.array_[i];
    return *this;
  }

  //Movement means no memory allocation.
  //Cannot throw exceptions.
  Value(Value &&val) noexcept : array_(val.array_)
  {
    //We've stolen the old value.
    val.array_ = nullptr;
  }

  //Cannot throw exceptions.
  Value &operator=(Value &&val) noexcept
  {
    //Clever trick. Since `val` is going to be destroyed soon anyway,
    //we swap his data with ours. His destructor will destroy our data.
    std::swap(array_, val.array_);
  }
};

사실, 우리는 객체를 움직일 수있게하면서 딥 카피를 금지하고 싶다면 그런 타입을 카피 불가능하게 만들 수도 있습니다.

struct Inner {int i;};

constexpr auto NUM_INNER = 5;
class Value
{
private:
  Inner *array_; //Normally has reference semantics.

public:
  Value() : array_(new Inner[NUM_INNER]){}

  //OK to delete even if nullptr
  ~Value() {delete[] array_;}

  Value(const Value &val) = delete;
  Value &operator=(const Value &val) = delete;

  //Movement means no memory allocation.
  //Cannot throw exceptions.
  Value(Value &&val) noexcept : array_(val.array_)
  {
    //We've stolen the old value.
    val.array_ = nullptr;
  }

  //Cannot throw exceptions.
  Value &operator=(Value &&val) noexcept
  {
    //Clever trick. Since `val` is going to be destroyed soon anyway,
    //we swap his data with ours. His destructor will destroy our data.
    std::swap(array_, val.array_);
  }
};

우리는 심지어 unique_ptr 의 사용을 통해 제로 규칙을 적용 할 수 있습니다.

struct Inner {int i;};

constexpr auto NUM_INNER = 5;
class Value
{
private:
  unique_ptr<Inner []>array_; //Move-only type.

public:
  Value() : array_(new Inner[NUM_INNER]){}

  //No need to explicitly delete. Or even declare.
  ~Value() = default; {delete[] array_;}

  //No need to explicitly delete. Or even declare.
  Value(const Value &val) = default;
  Value &operator=(const Value &val) = default;

  //Will perform an element-wise move.
  Value(Value &&val) noexcept = default;

  //Will perform an element-wise move.
  Value &operator=(Value &&val) noexcept = default;
};

정의

객체의 관찰 가능 상태가 해당 유형의 다른 모든 객체와 기능적으로 다른 경우 유형은 값 의미를가집니다. 즉, 개체를 복사하면 새 개체가 생기며 새 개체의 수정 사항은 이전 개체에서 전혀 볼 수 없습니다.

대부분의 기본 C ++ 유형은 값 의미를가집니다.

int i = 5;
int j = i; //Copied
j += 20;
std::cout << i; //Prints 5; i is unaffected by changes to j.

대부분의 표준 라이브러리 정의 유형은 값 의미 체계를 가지고 있습니다.

std::vector<int> v1(5, 12); //array of 5 values, 12 in each.
std::vector<int> v2 = v1; //Copies the vector.
v2[3] = 6; v2[4] = 9;
std::cout << v1[3] << " " << v1[4]; //Writes "12 12", since v1 is unchanged.

하나의 객체를 조작하면 상태가 다른 객체 내에서 변경되도록 해당 유형의 인스턴스가 관찰 가능한 상태를 다른 객체 (외부 객체)와 공유 할 수있는 경우 유형이 참조 의미를 갖습니다.

C ++ 포인터는 자신이 가리키는 객체와 관련하여 가치 의미론을 가지고 있지만 포인터가 가리키는 객체의 상태 와 관련하여 참조 의미를가집니다.

int *pi = new int(4);
int *pi2 = pi;
pi = new int(16);
assert(pi2 != pi); //Will always pass.

int *pj = pi;
*pj += 5;
std::cout << *pi; //Writes 9, since `pi` and `pj` reference the same object.

C ++ 참조에는 참조 의미 체계가 있습니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow