खोज…


गहरी नकल और समर्थन ले जाएँ

यदि कोई प्रकार मान शब्दार्थ रखना चाहता है, और उसे ऐसी वस्तुओं को संग्रहीत करने की आवश्यकता होती है जो गतिशील रूप से आवंटित की जाती हैं, तो प्रतिलिपि कार्यों पर, प्रकार को उन वस्तुओं की नई प्रतियां आवंटित करने की आवश्यकता होगी। इसे कॉपी असाइनमेंट के लिए भी करना होगा।

इस तरह की नकल को "डीप कॉपी" कहा जाता है। यह प्रभावी रूप से लेता है जो अन्यथा संदर्भ शब्दार्थ होता और इसे मूल्य शब्दार्थ में बदल देता:

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;
  }
};
सी ++ 11

मूवमेंट शब्दार्थ एक प्रकार के Value अनुमति देते हैं जो वास्तव में इसके संदर्भित डेटा की प्रतिलिपि बनाने से बचने के लिए है। यदि उपयोगकर्ता इस तरह से मूल्य का उपयोग करता है जो एक चाल को उकसाता है, तो ऑब्जेक्ट से "कॉपी किया गया" इसे संदर्भित डेटा को खाली छोड़ सकता है:

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