පිටපත් කිරීම සහ හුවමාරු කිරීම යනු කුමක්ද?


2013

මෙම මෝඩකම කුමක්ද සහ එය භාවිතා කළ යුත්තේ කවදාද? එය විසඳන්නේ කුමන ගැටලු ද? C ++ 11 භාවිතා කරන විට මෝඩකම වෙනස් වේද?

එය බොහෝ ස්ථානවල සඳහන් කර ඇතත්, අපට “එය කුමක්ද” යන ප්‍රශ්නෝත්තර පිළිතුරක් නොතිබුණි, එබැවින් මෙන්න එයයි. එය කලින් සඳහන් කළ ස්ථානවල අර්ධ ලැයිස්තුවක් මෙන්න:



2
නියමයි, මම මෙම ප්‍රශ්නය මගේ පිළිතුරෙන් අර්ථ නිරූපණය කිරීමට සම්බන්ධ කළෙමි .
fredoverflow

4
මෙම මෝඩකම පිළිබඳ පූර්ණ පැහැදිලි කිරීමක් තිබීම හොඳ අදහසකි, එය කොතරම් සුලභද යත්, සෑම කෙනෙක්ම ඒ ගැන දැන සිටිය යුතුය.
මැතිව් එම්

16
අවවාදයයි: පිටපත් / ස්වප් අයිඩියම් ප්‍රයෝජනවත් වීමට වඩා බොහෝ විට භාවිතා වේ. පිටපත් පැවරුමෙන් ශක්තිමත් ව්‍යතිරේක ආරක්ෂණ සහතිකයක් අවශ්‍ය නොවන විට එය බොහෝ විට කාර්ය සාධනයට හානිකර වේ. පිටපත් පැවරීම සඳහා ශක්තිමත් ව්‍යතිරේක ආරක්ෂාවක් අවශ්‍ය වූ විට, එය වඩා වේගවත් පිටපත් පැවරුම් ක්‍රියාකරුට අමතරව කෙටි ජනක ශ්‍රිතයක් මඟින් පහසුවෙන් සපයනු ලැබේ. බලන්න slideshare.net/ripplelabs/howard-hinnant-accu2014 පිටපතක් / හුවමාරු උපකරණ කට්ටලය ප්රයෝජනවත් උපකරණයක් වේ: 53. සාරාංශය - කදා 43. නමුත් එය අධික ලෙස අලෙවිකර ඇති අතර පසුව බොහෝ විට අපයෝජනයට ලක්ව ඇත.
හොවාර්ඩ් හිනන්ට්

2
OwHowardHinnant: ඔව්, ඒ සඳහා +1 කරන්න. මම මෙය ලිවූයේ සෑම C ++ ප්‍රශ්නයක්ම පාහේ "පිටපතක් පිටපත් කිරීමේදී මගේ පන්තිය බිඳ වැටීමට උදව් කරන්න" යනුවෙනි. මෙය මගේ ප්‍රතිචාරයයි. ඔබට වැඩ කරන පිටපත් / චලනය-අර්ථකථන හෝ වෙනත් ඕනෑම දෙයක් අවශ්‍ය විට එය සුදුසු ය, එවිට ඔබට වෙනත් දේ කරා ගමන් කළ හැකිය, නමුත් එය ඇත්තෙන්ම ප්‍රශස්ත නොවේ. එය ප්‍රයෝජනවත් වේ යැයි ඔබ සිතන්නේ නම්, මගේ පිළිතුරේ ඉහළින්ම වියාචනයක් ඉදිරිපත් කිරීමට නිදහස් වන්න.
GManNickG

Answers:


2195

දළ විශ්ලේෂණය

අපට පිටපත් හා හුවමාරු මෝඩකම අවශ්‍ය වන්නේ ඇයි?

(අ සම්පතක් කළමනාකරණය කරන කිසිදු පන්ති දවටනය ස්මාර්ට් පහිටුම් දක්වනය මෙන්) ක්රියාත්මක කිරීමට අවශ්ය ද බිග් ත්රී . පිටපත් සාදන්නා සහ විනාශ කරන්නාගේ අරමුණු හා ක්‍රියාත්මක කිරීම සරල වුවත්, පිටපත් පැවරීමේ ක්‍රියාකරු වඩාත් සූක්ෂම හා දුෂ්කර ය. එය කළ යුත්තේ කෙසේද? වළක්වා ගත යුතු අන්තරායන් මොනවාද?

මෙම පිටපත්-සහ-swap බස් වහරක් විසඳුම වන අතර, අලංකාර දේවල් දෙකක් සපුරා ගැනීම සඳහා පැවරුම ක්රියාකරු සහාය: මග කේතය අනුපිටපතක් , සහ ලබා ශක්තිමත් හැර සහතිකයක් .

එය ක්‍රියාත්මක වන්නේ කෙසේද?

සංකල්පමය වශයෙන් , දත්ත වල දේශීය පිටපතක් නිර්මාණය කිරීම සඳහා පිටපත්-ඉදිකිරීම්කරුගේ ක්‍රියාකාරීත්වය භාවිතා කිරීමෙන් එය ක්‍රියාත්මක වන අතර පසුව පිටපත් කරන ලද දත්ත swapශ්‍රිතයක් සමඟ ගෙන පැරණි දත්ත නව දත්ත සමඟ හුවමාරු කර ගනී . පසුව තාවකාලික පිටපත විනාශ වන අතර පැරණි දත්ත රැගෙන යයි. නව දත්තවල පිටපතක් අපට ඉතිරිව ඇත.

පිටපත්-හා-හුවමාරු මෝඩකම භාවිතා කිරීම සඳහා, අපට කරුණු තුනක් අවශ්‍ය වේ: වැඩ කරන පිටපත් සාදන්නෙකු, වැඩ කරන විනාශ කරන්නෙකු (දෙකම ඕනෑම එතීමක පදනම වේ, එබැවින් කෙසේ හෝ සම්පූර්ණ විය යුතුය), සහ swapශ්‍රිතයක්.

Swap ශ්‍රිතය යනු විසි නොකරන ශ්‍රිතයක් වන අතර එය පන්තියක වස්තු දෙකක් මාරු කරයි . std::swapඅපේම දෑ ලබා දීම වෙනුවට භාවිතා කිරීමට අප පෙළඹෙනු ඇත , නමුත් මෙය කළ නොහැකි වනු ඇත; std::swapඑය ක්‍රියාත්මක කිරීමේදී පිටපත්-ඉදිකිරීම්කරු සහ පිටපත්-පැවරුම් ක්‍රියාකරු භාවිතා කරයි, අපි අවසානයේ උත්සාහ කරන්නේ පැවරුම් ක්‍රියාකරු නිර්වචනය කිරීමටයි!

(එපමණක් නොව, නුසුදුසු ඇමතුම් swapඅපගේ අභිරුචි හුවමාරු ක්‍රියාකරු භාවිතා කරනු ඇත, අපගේ පන්තියේ අනවශ්‍ය ඉදිකිරීම් සහ විනාශයන් මඟ std::swapහැරෙනු ඇත.)


ගැඹුරු පැහැදිලි කිරීමක්

ඉලක්කය

කොන්ක්‍රීට් නඩුවක් සලකා බලමු. අපට අවශ්‍ය වන්නේ වෙනත් ආකාරයකින් වැඩකට නැති පන්තියක ගතික අරාවකි. අපි වැඩකරන ඉදිකිරීම්කරුවෙකු, පිටපත් සාදන්නෙකු සහ විනාශ කරන්නෙකු සමඟ ආරම්භ කරමු:

#include <algorithm> // std::copy
#include <cstddef> // std::size_t

class dumb_array
{
public:
    // (default) constructor
    dumb_array(std::size_t size = 0)
        : mSize(size),
          mArray(mSize ? new int[mSize]() : nullptr)
    {
    }

    // copy-constructor
    dumb_array(const dumb_array& other)
        : mSize(other.mSize),
          mArray(mSize ? new int[mSize] : nullptr),
    {
        // note that this is non-throwing, because of the data
        // types being used; more attention to detail with regards
        // to exceptions must be given in a more general case, however
        std::copy(other.mArray, other.mArray + mSize, mArray);
    }

    // destructor
    ~dumb_array()
    {
        delete [] mArray;
    }

private:
    std::size_t mSize;
    int* mArray;
};

මෙම පන්තිය අරාව සාර්ථකව කළමනාකරණය කරයි, නමුත් එය operator=නිවැරදිව ක්‍රියා කළ යුතුය.

අසාර්ථක විසඳුමක්

බොළඳ ක්‍රියාත්මක කිරීමක් පෙනෙන්නේ කෙසේද යන්න මෙන්න:

// the hard part
dumb_array& operator=(const dumb_array& other)
{
    if (this != &other) // (1)
    {
        // get rid of the old data...
        delete [] mArray; // (2)
        mArray = nullptr; // (2) *(see footnote for rationale)

        // ...and put in the new
        mSize = other.mSize; // (3)
        mArray = mSize ? new int[mSize] : nullptr; // (3)
        std::copy(other.mArray, other.mArray + mSize, mArray); // (3)
    }

    return *this;
}

අපි කියනවා අපි ඉවරයි කියලා; මෙය දැන් කාන්දුවීම් නොමැතිව අරාව කළමනාකරණය කරයි. කෙසේ වෙතත්, එය ගැටළු තුනකින් පෙළෙන අතර එය කේතයේ අනුපිළිවෙලින් සලකුණු කර (n)ඇත.

  1. පළමුවැන්න ස්වයං පැවරුම් පරීක්ෂණයයි. මෙම චෙක්පත අරමුණු දෙකකට සේවය කරයි: එය ස්වයං පැවරුම මත අනවශ්‍ය කේත ධාවනය කිරීමෙන් අපව වළක්වා ගැනීමට පහසු ක්‍රමයක් වන අතර, එය සියුම් දෝෂ වලින් අපව ආරක්ෂා කරයි (එය උත්සාහ කර පිටපත් කිරීමට පමණක් අරාව මකා දැමීම වැනි). නමුත් අනෙක් සෑම අවස්ථාවකම එය හුදෙක් වැඩසටහන මන්දගාමී කිරීමට සහ කේතයේ ශබ්දය ලෙස ක්‍රියා කරයි; ස්වයං පැවරුම කලාතුරකින් සිදු වේ, එබැවින් බොහෝ විට මෙම චෙක්පත නාස්තියකි. එය නොමැතිව ක්‍රියාකරුට නිසි ලෙස ක්‍රියා කළ හැකි නම් වඩා හොඳය.

  2. දෙවැන්න නම් එය සපයන්නේ මූලික ව්‍යතිරේක සහතිකයක් පමණි. නම් new int[mSize]අසමත්, *thisවිකරණය කොට තිබේ වනු ඇත. (එනම්, ප්‍රමාණය වැරදියි සහ දත්ත නැති වී ඇත!) ශක්තිමත් ව්‍යතිරේක සහතිකයක් සඳහා, එය සමාන දෙයක් විය යුතුය:

    dumb_array& operator=(const dumb_array& other)
    {
        if (this != &other) // (1)
        {
            // get the new data ready before we replace the old
            std::size_t newSize = other.mSize;
            int* newArray = newSize ? new int[newSize]() : nullptr; // (3)
            std::copy(other.mArray, other.mArray + newSize, newArray); // (3)
    
            // replace the old data (all are non-throwing)
            delete [] mArray;
            mSize = newSize;
            mArray = newArray;
        }
    
        return *this;
    }
  3. කේතය පුළුල් වී ඇත! එය අපව තුන්වන ගැටලුවට යොමු කරයි: කේත අනුපිටපත් කිරීම. අපගේ පැවරුම් ක්‍රියාකරු අප දැනටමත් වෙනත් තැනක ලියා ඇති සියලුම කේත effectively ලදායී ලෙස අනුපිටපත් කරයි, එය භයානක දෙයකි.

අපගේ නඩුවේදී, එහි හරය පේළි දෙකක් පමණි (වෙන් කිරීම සහ පිටපත), නමුත් වඩාත් සංකීර්ණ සම්පත් සමඟ මෙම කේත පිපිරීම තරමක් කරදරයක් විය හැකිය. අප කිසි විටෙකත් නැවත නැවත නොකිරීමට උත්සාහ කළ යුතුය.

(කෙනෙකුට සිතිය හැකිය: එක් සම්පතක් නිවැරදිව කළමනාකරණය කිරීම සඳහා මෙම කේතය අවශ්‍ය නම්, මගේ පන්තිය එකකට වඩා කළමනාකරණය කරන්නේ නම් කුමක් කළ යුතුද? මෙය වලංගු කාරණයක් ලෙස පෙනෙන්නට තිබුණද, ඇත්ත වශයෙන්ම එය සුළුපටු නොවන try/ catchවගන්ති අවශ්‍ය වුවද, මෙය නොවන පංතියක් එක් සම්පතක් පමණක් කළමනාකරණය කළ යුතු නිසා !

සාර්ථක විසඳුමක්

සඳහන් කළ පරිදි, පිටපත්-හා-හුවමාරු මෝඩය මෙම සියලු ගැටලු විසඳනු ඇත. නමුත් මේ මොහොතේ, අපට එකක් හැර අනෙක් සියලුම අවශ්‍යතා ඇත: swapශ්‍රිතයක්. තුනේ රීතිය අපගේ පිටපත්-ඉදිකිරීම්කරු, පැවරුම් ක්‍රියාකරු සහ විනාශ කරන්නාගේ පැවැත්මට සාර්ථකව ඇතුළත් වන අතර, එය සැබවින්ම "ලොකු තුන සහ අඩක්" ලෙස හැඳින්විය යුතුය: ඔබේ පන්තිය සම්පතක් කළමනාකරණය කරන ඕනෑම වේලාවක එය swapශ්‍රිතයක් සැපයීම අර්ථවත් කරයි .

අපගේ පන්තියට swap ක්‍රියාකාරිත්වය එක් කළ යුතු අතර, අපි එය පහත පරිදි කරන්නෙමු †:

class dumb_array
{
public:
    // ...

    friend void swap(dumb_array& first, dumb_array& second) // nothrow
    {
        // enable ADL (not necessary in our case, but good practice)
        using std::swap;

        // by swapping the members of two objects,
        // the two objects are effectively swapped
        swap(first.mSize, second.mSize);
        swap(first.mArray, second.mArray);
    }

    // ...
};

( ඇයිද යන්න පැහැදිලි කිරීම මෙන්නpublic friend swap .) දැන් අපට අපගේ dumb_arrayහුවමාරු කර ගත හැකිවා පමණක් නොව, සාමාන්‍යයෙන් හුවමාරුව වඩාත් කාර්යක්ෂම විය හැකිය; එය හුදෙක් සම්පූර්ණ අරා වෙන් කිරීම හා පිටපත් කිරීම වෙනුවට දර්ශකයන් සහ ප්‍රමාණයන් මාරු කරයි. ක්‍රියාකාරීත්වය සහ කාර්යක්ෂමතාව පිළිබඳ මෙම ප්‍රසාද දීමනාව හැරුණු විට, අපි දැන් පිටපත් හා හුවමාරු මෝඩය ක්‍රියාත්මක කිරීමට සූදානම්.

වැඩිදුර කලබලයකින් තොරව, අපගේ පැවරුම් ක්‍රියාකරු:

dumb_array& operator=(dumb_array other) // (1)
{
    swap(*this, other); // (2)

    return *this;
}

ඒක තමයි! එක් කඩාවැටීමකින්, ගැටළු තුනම එකවරම විසඳනු ලැබේ.

එය ක්‍රියාත්මක වන්නේ ඇයි?

අපි මුලින්ම වැදගත් තේරීමක් දකිමු: පරාමිති තර්කය අගය අනුව ගනු ලැබේ . යමෙකුට පහත සඳහන් දෑ පහසුවෙන් කළ හැකි අතර (ඇත්ත වශයෙන්ම, මෝඩයන් බොහොමයක් බොළඳ ලෙස ක්‍රියාත්මක කරයි):

dumb_array& operator=(const dumb_array& other)
{
    dumb_array temp(other);
    swap(*this, temp);

    return *this;
}

අපට වැදගත් ප්‍රශස්තිකරණ අවස්ථාවක් අහිමි වේ. එපමණක් නොව, C ++ 11 හි මෙම තේරීම ඉතා වැදගත් වන අතර එය පසුව සාකච්ඡා කෙරේ. (සාමාන්‍ය සටහනක, ඉතා ප්‍රයෝජනවත් මාර්ගෝපදේශයක් පහත පරිදි වේ: ඔබ යම් ශ්‍රිතයක යම් පිටපතක් සෑදීමට යන්නේ නම්, එය පරාමිති ලැයිස්තුවේ සම්පාදකයාට කිරීමට ඉඩ දෙන්න. ‡)

කෙසේ හෝ වේවා, අපගේ සම්පත් ලබා ගැනීමේ මෙම ක්‍රමය කේත අනුපිටපත් ඉවත් කිරීම සඳහා යතුරයි: පිටපත සෑදීම සඳහා අපට පිටපත්-ඉදිකිරීම්කරුගෙන් කේතය භාවිතා කළ හැකි අතර, එයින් කිසි විටෙකත් නැවත නැවත කිරීමට අවශ්‍ය නොවේ. දැන් පිටපත සාදන ලද බැවින්, අපි හුවමාරු වීමට සූදානම්.

සියලුම නව දත්ත දැනටමත් වෙන් කර ඇති, පිටපත් කර ඇති අතර භාවිතයට සුදානම් බව ශ්‍රිතයට ඇතුළු වූ පසු නිරීක්ෂණය කරන්න. නොමිලේ අපට ව්‍යතිරේක සහතිකයක් ලබා දෙන්නේ මෙයයි: පිටපත තැනීම අසාර්ථක වුවහොත් අපි ශ්‍රිතයට ඇතුළු නොවන්නෙමු. එබැවින් තත්වය වෙනස් කළ නොහැක *this. (ප්‍රබල ව්‍යතිරේක සහතිකයක් සඳහා අප මීට පෙර අතින් කළ දේ, සම්පාදකයා දැන් අප වෙනුවෙන් කරන්නේ; කෙතරම් කාරුණිකද?)

මේ අවස්ථාවේදී අපි ගෙදරින් නිදහස් වෙමු swap. අපි අපගේ වර්තමාන දත්ත පිටපත් කළ දත්ත සමඟ හුවමාරු කර ගනිමින්, අපගේ තත්වය ආරක්ෂිතව වෙනස් කර, පැරණි දත්ත තාවකාලික බවට පත් කරමු. ශ්‍රිතය නැවත පැමිණෙන විට පැරණි දත්ත මුදා හරිනු ලැබේ. (පරාමිතියේ විෂය පථය අවසන් වන විට සහ එහි විනාශ කරන්නා ලෙස හැඳින්වේ.)

මෝඩය කිසිදු කේතයක් පුනරාවර්තනය නොකරන හෙයින්, අපට ක්‍රියාකරු තුළ දෝෂ හඳුන්වා දිය නොහැක. මෙයින් අදහස් කරන්නේ ස්වයං-පැවරුම් පරීක්‍ෂණයක අවශ්‍යතාවයෙන් අප ඉවත් වන අතර තනි ඒකාකාරී ක්‍රියාවලියක් සඳහා ඉඩ ලබා දෙන බවයි operator=. (මීට අමතරව, අපට ස්වයං-පැවරුම් නොවන කාර්ය සාධන ද penalty ුවමක් තවදුරටත් නොමැත.)

එය පිටපත් හා හුවමාරු මෝඩකමයි.

C ++ 11 ගැන කුමක් කිව හැකිද?

C ++ හි ඊළඟ අනුවාදය, C ++ 11, අප සම්පත් කළමනාකරණය කරන්නේ කෙසේද යන්නට ඉතා වැදගත් වෙනසක් කරයි: තුන්වන රීතිය දැන් හතරේ රීතිය (එකහමාරක්) වේ. මන්ද? අපගේ සම්පත පිටපත් කිරීමට හා ගොඩ නැගීමට අපට හැකියාව තිබිය යුතු පමණක් නොව, එය ගෙනයාමට හා ඉදිකිරීමටද අපට අවශ්‍යය .

වාසනාවකට අපට මෙය පහසුය:

class dumb_array
{
public:
    // ...

    // move constructor
    dumb_array(dumb_array&& other) noexcept ††
        : dumb_array() // initialize via default constructor, C++11 only
    {
        swap(*this, other);
    }

    // ...
};

මොකද මෙතන වෙන්නෙ? චලනය-ඉදිකිරීමේ පරමාර්ථය සිහිපත් කරන්න: පංතියේ වෙනත් අවස්ථාවකින් සම්පත් ලබා ගැනීම, එය පැවරිය හැකි හා විනාශකාරී යැයි සහතික කළ හැකි තත්වයකට පත් කිරීම.

එබැවින් අප කර ඇති දේ ඉතා සරල ය: පෙරනිමි ඉදිකිරීම්කරු (C ++ 11 අංගයක්) හරහා ආරම්භ කරන්න, ඉන්පසු මාරු වන්න other; අපගේ පංතියේ පෙරනිමියෙන් සාදන ලද නිදසුනක් ආරක්ෂිතව පැවරීමට හා විනාශ කිරීමට හැකි බව අපි දනිමු, එබැවින් otherහුවමාරු කිරීමෙන් පසුවද එය කළ හැකි බව අපි දනිමු .

(සමහර සම්පාදකයින් විසින් ඉදිකිරීම්කරුවන්ගේ නියෝජිත කණ්ඩායමට සහාය නොදක්වන බව සලකන්න. මේ අවස්ථාවේ දී, අප විසින් අතින් පෙරනිමිය පන්තිය තැනීමට සිදුවේ. මෙය අවාසනාවන්ත නමුත් වාසනාවකට මෙන් සුළු කාර්යයකි.)

එය ක්‍රියාත්මක වන්නේ ඇයි?

අපගේ පන්තියට අප විසින් කළ යුතු එකම වෙනස එයයි, එබැවින් එය ක්‍රියාත්මක වන්නේ ඇයි? පරාමිතිය වටිනාකමක් මිස යොමු කිරීමක් නොවීමට අප ගත් වැදගත් තීරණය මතක තබා ගන්න:

dumb_array& operator=(dumb_array other); // (1)

දැන්, otherඅගය සමඟ ආරම්භ කරන්නේ නම්, එය චලනය වනු ඇත . පරිපූර්ණ. C ++ 03 ඒ හා සමානව, තර්කය අනුව අගය ගෙන අපගේ පිටපත්-ඉදිකිරීම්කරුගේ ක්‍රියාකාරිත්වය නැවත භාවිතා කරමු, C ++ 11 ස්වයංක්‍රීයව චලනය-ඉදිකිරීම්කරු සුදුසු විට තෝරා ගනු ඇත. (ඇත්ත වශයෙන්ම, කලින් සම්බන්ධිත ලිපියේ සඳහන් කර ඇති පරිදි, අගය පිටපත් කිරීම / ගෙනයාම හුදෙක් මුළුමනින්ම ඉවත් කළ හැකිය.)

ඒ නිසා පිටපත් හා හුවමාරු මෝඩකම අවසන් වේ.


පාද සටහන්

* අප mArrayඅහෝසි කරන්නේ ඇයි? මක්නිසාද යත්, ක්‍රියාකරුගේ තවත් කේතයක් විසි කරන්නේ නම්, විනාශ කරන්නා ලෙස dumb_arrayහැඳින්විය හැක; එය අහෝසි නොකර එය සිදුවුවහොත්, අපි දැනටමත් මකා දමා ඇති මතකය මකා දැමීමට උත්සාහ කරමු! ශුන්‍යය මකා දැමීම කිසිදු ක්‍රියාවක් නොවන බැවින් අපි එය ශුන්‍ය ලෙස සැකසීමෙන් වැළකී සිටිමු.

std::swapType අප අපේ වර්ගයට විශේෂ ize විය යුතු බවත් , පංතියේ swapනොමිලේ ශ්‍රිතයක් ලබා දිය යුතු බවත් වෙනත් ප්‍රකාශයන් ඇත swap. නමුත් මේ සියල්ල අනවශ්‍යය: නිසි ලෙස භාවිතා කිරීම swapසුදුසුකම් නොලත් ඇමතුමක් හරහා වන අතර අපගේ කාර්යය වනු ඇත ADL හරහා හමු විය . එක් කාර්යයක් කරනු ඇත.

Simple හේතුව සරලයි: ඔබ සතුව සම්පතක් ඇති විට, ඔබට අවශ්‍ය ඕනෑම තැනකට එය මාරු කර / හෝ ගෙන යා හැකිය (C ++ 11). පරාමිති ලැයිස්තුවේ පිටපත සෑදීමෙන්, ඔබ උපරිම ප්‍රශස්තිකරණය කරයි.

Move චලනය වන ඉදිකිරීම්කරු සාමාන්‍යයෙන් විය යුතුය noexcept, එසේ නොමැතිනම් සමහර කේත (උදා: std::vectorප්‍රමාණය වෙනස් කිරීමේ තර්කනය) යම් පියවරක් අර්ථවත් වන විටදී පවා පිටපත් සාදන්නා භාවිතා කරයි. ඇත්ත වශයෙන්ම, ඇතුළත කේතය ව්‍යතිරේකයන් විසි නොකරන්නේ නම් පමණක් එය සලකුණු කරන්න.


17
@ ජී මෑන්: සම්පත් කිහිපයක් එකවර කළමනාකරණය කරන පන්තියක් අසාර්ථක වනු ඇතැයි මම තර්ක කරමි (ව්‍යතිරේක ආරක්ෂාව නපුරු සිහිනයක් බවට පත්වේ) සහ එක් පන්තියක් එක් සම්පතක් කළමනාකරණය කරන ලෙස හෝ එය ව්‍යාපාර ක්‍රියාකාරිත්වය සහ කළමනාකරුවන් භාවිතා කරන ලෙස මම තරයේ නිර්දේශ කරමි.
මැතිව් එම්

22
Swap ක්‍රමය මෙහි මිතුරෙකු ලෙස ප්‍රකාශයට පත් කරන්නේ ඇයිදැයි මට නොතේරේ.
szx

11
dasd: එය ADL හරහා සොයා ගැනීමට ඉඩ දීම.
GManNickG

9
uneuviemeporte: වරහන් සමඟ අරා මූලද්‍රව්‍ය පෙරනිමිය ආරම්භ වේ. නොමැතිව, ඔවුන් ආරම්භක නොවේ. පිටපත් සාදන්නා තුළ අපි කෙසේ හෝ අගයන් නැවත ලියනු ඇති බැවින් අපට ආරම්භය මඟ හැරිය හැක.
GManNickG

10
u නියුවෙම්පෝර්ට්: ඔබට swapහමුවන බොහෝ සාමාන්‍ය කේතයන්හි වැඩ කිරීමට අවශ්‍ය නම් ඒඩීඑල් තුළ ඔබ සොයා ගත යුතුය boost::swap. Swap යනු C ++ හි ඇති ව්‍යාකූල කාරණයක් වන අතර, සාමාන්‍යයෙන් අපි සියලු දෙනාම එකඟ වී ඇත්තේ එක් ප්‍රවේශ ස්ථානයක් හොඳම (අනුකූලතාව සඳහා) වන අතර, සාමාන්‍යයෙන් එය කළ හැකි එකම ක්‍රමය නිදහස් ශ්‍රිතයකි ( intswap සාමාජිකයෙකු සිටිය නොහැක, උදාහරණයක් වශයෙන්). යම් පසුබිමක් සඳහා මගේ ප්‍රශ්නය බලන්න .
GManNickG

274

පැවරුම, එහි හදවත, එක විට පියවර දෙකක් වේ: වස්තුව පැරණි රාජ්ය සදාම්ගේ සහ පිටපතක් ලෙස එහි නව රාජ්ය ගොඩනැගීමේ වෙනත් වස්තුවක් ගේ රාජ්ය.

මූලික වශයෙන්, විනාශ කරන්නා සහ පිටපත් සාදන්නා කරන්නේ එයයි, එබැවින් පළමු අදහස වනුයේ කාර්යය ඔවුන්ට පැවරීමයි. කෙසේ වෙතත්, විනාශය අසාර්ථක නොවිය යුතු බැවින්, ඉදිකිරීම් සිදු විය හැකි අතර, ඇත්ත වශයෙන්ම අපට එය වෙනත් ආකාරයකින් කිරීමට අවශ්‍යය : පළමුව ruc ලදායී කොටස සිදු කරන්න , එය සාර්ථක වුවහොත් විනාශකාරී කොටස කරන්න . පිටපත් කිරීම සහ හුවමාරු කිරීම යනු එය කළ හැකි ක්‍රමයකි: එය පළමුව පන්තියේ පිටපත් සාදන්නෙකු තාවකාලික වස්තුවක් නිර්මාණය කිරීම සඳහා කැඳවයි, පසුව එහි දත්ත තාවකාලික දේ සමඟ හුවමාරු කර ගනී, පසුව තාවකාලික විනාශ කරන්නාට පැරණි තත්වය විනාශ කිරීමට ඉඩ දෙයි.
සිටswap()කිසි විටෙකත් අසමත් නොවිය යුතුය, අසමත් විය හැකි එකම කොටස පිටපත් තැනීමයි. එය පළමුව සිදු කරනු ලබන අතර, එය අසමත් වුවහොත් ඉලක්කගත වස්තුවෙහි කිසිවක් වෙනස් නොවේ.

පැවරුම් ක්‍රියාකරුගේ (යොමු නොවන) පරාමිතිය ආරම්භ කිරීමෙන් පිටපත සිදු කිරීමෙන් එහි පිරිපහදු කළ ස්වරූපයෙන් පිටපත් හා හුවමාරුව ක්‍රියාත්මක වේ:

T& operator=(T tmp)
{
    this->swap(tmp);
    return *this;
}

1
පිටපත, හුවමාරුව සහ විනාශය සඳහන් කිරීම තරම්ම pimpl ගැන සඳහන් කිරීම වැදගත් යැයි මම සිතමි. හුවමාරුව ඉන්ද්‍රජාලිකව ව්‍යතිරේක-ආරක්ෂිත නොවේ. දර්ශක හුවමාරු කිරීම ව්‍යතිරේක-ආරක්ෂිත බැවින් එය ව්‍යතිරේක-ආරක්ෂිත ය. ඔබ නෑ ඇති වන pimpl භාවිතා කිරීමට, නමුත් ඔබ එසේ නම් ඔබ සාමාජික එක් එක් ස්වැප් හැර-ආරක්ෂිත බව තහවුරු කළ යුතුය. මෙම සාමාජිකයින්ට වෙනස් විය හැකි විට එය බියකරු සිහිනයක් විය හැකි අතර ඔවුන් පිම්පල් පිටුපස සැඟවී සිටින විට එය සුළුපටු ය. එවිට, එවිට pimpl හි පිරිවැය පැමිණේ. බොහෝ විට ව්‍යතිරේක-ආරක්ෂාව කාර්ය සාධනයේ පිරිවැයක් දරයි යන නිගමනයට අපව යොමු කරයි.
විල්හෙල්ම්ටෙල්

7
std::swap(this_string, that)විසි කිරීමේ සහතිකයක් ලබා නොදේ. එය ශක්තිමත් ව්‍යතිරේක ආරක්ෂාවක් සපයයි, නමුත් විසි කිරීමේ සහතිකයක් නොවේ.
විල්හෙල්ම්ටෙල්

11
ill විල්හෙල්ම්ටෙල්: සී ++ 03 හි විසි කළ හැකි ව්‍යතිරේකයන් ගැන සඳහනක් නොමැත std::string::swap(එය හඳුන්වනු ලබන්නේ std::swap). C ++ 0x දී std::string::swapnoexceptසහ ව්යතිරේක විසි නොකළ යුතු ය.
ජේම්ස් මැක්නෙලිස්

2
@sbi @JamesMcNellis හරි, නමුත් කාරණය තවමත් පවතී: ඔබට පන්ති වර්ගයේ සාමාජිකයන් සිටී නම් ඔවුන් මාරු කිරීම කිසිසේත්ම ඉවත දැමිය නොහැකි බවට වග බලා ගත යුතුය. ඔබට තනි සාමාජිකයෙකු සිටී නම් එය දර්ශකයකි. එසේ නොමැති නම් එසේ නොවේ.
විල්හෙල්ම්ටෙල්

2
ill විල්හෙල්ම්ටෙල්: මම සිතුවේ එය හුවමාරු වීමේ ලක්ෂ්‍යයයි: එය කිසි විටෙකත් විසි නොකරන අතර එය සැමවිටම ඕ (1) (ඔව්, මම දනිමි std::array...)
sbi

44

දැනටමත් හොඳ පිළිතුරු කිහිපයක් තිබේ. මම ප්‍රධාන වශයෙන් අවධානය යොමු කරන්නේ ඔවුන් සතුව නොමැති යැයි මා සිතන දෙයයි - පිටපත් හා හුවමාරු මෝඩකම සමඟ ඇති “අවාසි” පිළිබඳ පැහැදිලි කිරීමක් ....

පිටපත් කිරීම සහ හුවමාරු කිරීම යනු කුමක්ද?

හුවමාරු ශ්‍රිතයක් අනුව පැවරුම් ක්‍රියාකරු ක්‍රියාත්මක කිරීමේ ක්‍රමයක්:

X& operator=(X rhs)
{
    swap(rhs);
    return *this;
}

මූලික අදහස නම්:

  • වස්තුවකට පැවරීමේ වඩාත්ම දෝෂ සහිත කොටස වන්නේ නව රාජ්‍ය අවශ්‍යතා ලබා ගන්නා සම්පත් සහතික කිරීමයි (උදා: මතකය, විස්තර කරන්නන්)

  • වස්තුවෙහි වත්මන් තත්වය වෙනස් කිරීමට පෙර (එනම් *this) නව අගයේ පිටපතක් සාදනු ලැබුවහොත් එය අත්පත් කර ගැනීමට උත්සාහ කළ හැකිය , එම නිසා යොමු කිරීම වෙනුවට අගය (එනම් පිටපත් කිරීම) rhsපිළිගනු ලැබේ.

  • දේශීය පිටපතක් රාජ්ය හුවමාරු rhsසහ *thisසාමාන්යයෙන් විභව අසාර්ථක / ව්යතිරේක තොරව කරන්න සාපේක්ෂ වශයෙන් පහසු, දේශීය පිටපතක් ලබාදෙන වස්තුවක් සඳහා තරම් පසුව යම් විශේෂිත රාජ්ය අවශ්ය නොවේ (හුදෙක් ලකුණු කිරීමට destructor සඳහා රාජ්ය සුදුසු අවශ්ය, මාරු සිට> = C ++ 11)

එය භාවිතා කළ යුත්තේ කවදාද? (එය විසඳන්නේ කුමන ගැටළු [/ නිර්මාණය] ද ?)

  • ව්‍යතිරේකයක් විසි කරන පැවරුමකින් බලපෑමට ලක් නොවී පැවරීමට ඔබට අවශ්‍ය වූ විට, ඔබට swapශක්තිමත් ව්‍යතිරේක සහතිකයක් ඇති බව හෝ ලිවිය හැකි යැයි උපකල්පනය කර , අසමත් විය නොහැකි / throw..

  • (සරල) පිටපත් සාදන්නා swapසහ විනාශ කිරීමේ කාර්යයන් අනුව පැවරුම් ක්‍රියාකරු නිර්වචනය කිරීමට ඔබට පිරිසිදු, තේරුම් ගැනීමට පහසු, ශක්තිමත් ක්‍රමයක් අවශ්‍ය වූ විට .

    • පිටපතක් හා හුවමාරුවක් ලෙස ස්වයං-පැවරුම නොසලකා හරින ලද අවස්ථා මඟහරවා ගනී.

  • පැවරුමේදී අමතර තාවකාලික වස්තුවක් තිබීම මඟින් කිසියම් කාර්ය සාධන ද penalty ුවමක් හෝ මොහොතකින් වැඩි සම්පත් භාවිතය ඔබේ යෙදුමට වැදගත් නොවන විට. ⁂

Wing swapවිසි කිරීම: පොයින්ටර් මගින් වස්තූන් ලුහුබඳින දත්ත සාමාජිකයින් විශ්වාසදායක ලෙස හුවමාරු කර ගත හැකි නමුත් විසි-රහිත හුවමාරුවක් නොමැති, හෝ හුවමාරු කිරීම X tmp = lhs; lhs = rhs; rhs = tmp;හෝ පිටපත් කිරීම-ඉදිකිරීම හෝ පැවරුම ලෙස ක්‍රියාත්මක කළ යුතු දර්ශක නොවන දත්ත සාමාජිකයන්. සමහර දත්ත සාමාජිකයන් මාරු කර තැබීමට අසමත් වීමේ හැකියාව තවමත් ඇති අතර අනෙක් ඒවා එසේ නොවේ. std::stringජේම්ස් වෙනත් පිළිතුරක් ගැන අදහස් දක්වන පරිදි මෙම විභවය සී ++ 03 ට පවා අදාළ වේ :

il විල්හෙල්ම්ටෙල්: සී ++ 03 හි, std :: string :: swap (එය std :: swap ලෙස හැඳින්වේ) විසින් විසි කළ හැකි ව්‍යතිරේකයන් ගැන සඳහනක් නොමැත. C ++ 0x හි, std :: string :: swap යනු අනපේක්ෂිත වන අතර ව්‍යතිරේකයන් විසි නොකළ යුතුය. - ජේම්ස් මැක්නෙලිස් දෙසැම්බර් 22 '10 ට 15:24


Object විශේෂිත වස්තුවකින් පැවරීමේදී බුද්ධිමත් යැයි පෙනෙන පැවරුම් ක්‍රියාකරු ක්‍රියාත්මක කිරීම ස්වයං පැවරුම සඳහා පහසුවෙන් අසමත් විය හැකිය. ග්‍රාහක කේතය ස්වයං පැවරුමකට පවා උත්සාහ කරනු ඇතැයි සිතිය නොහැකි යැයි පෙනෙන්නට තිබුණද, බහාලුම්වල ඇල්ගෝ මෙහෙයුම් වලදී එය සාපේක්ෂව පහසුවෙන් සිදුවිය හැකිය, x = f(x);කේත සහිතව f(සමහර විට සමහර #ifdefශාඛා සඳහා පමණි ) සාර්ව අලා #define f(x) xහෝ ශ්‍රිතයක් යොමු කිරීමක් xහෝ නැවත යොමු කිරීමක් හෝ (අකාර්යක්ෂම නමුත් සංක්ෂිප්ත) කේතය වැනි x = c1 ? x * 2 : c2 ? x / 2 : x;). උදාහරණයක් වශයෙන්:

struct X
{
    T* p_;
    size_t size_;
    X& operator=(const X& rhs)
    {
        delete[] p_;  // OUCH!
        p_ = new T[size_ = rhs.size_];
        std::copy(p_, rhs.p_, rhs.p_ + rhs.size_);
    }
    ...
};

ස්වයං-පැවරුම, ඉහත කේතය delete මත වන x.p_;, ලකුණු p_අලුතින් වෙන් ගොඩක් ප්රදේශය, එවකට කියවීමට උත්සාහ uninitialised බව සද්දෙන් කිසිවක් නොවේ නම්, එහි (අනිශ්චිත හැසිරීම) දත්ත, copyසෑම just- කිරීමට ස්වයං පැවරුම උත්සාහ විනාශ වූ 'ටී'!


Temp අමතර තාවකාලික භාවිතය නිසා (ක්‍රියාකරුගේ පරාමිතිය පිටපත් සාදන විට) පිටපත්-හා-හුවමාරු මෝඩතාවයට අකාර්යක්ෂමතා හෝ සීමාවන් හඳුන්වා දිය හැකිය:

struct Client
{
    IP_Address ip_address_;
    int socket_;
    X(const X& rhs)
      : ip_address_(rhs.ip_address_), socket_(connect(rhs.ip_address_))
    { }
};

මෙන්න, අතින් ලියන ලද Client::operator=ඒවා *thisදැනටමත් එකම සේවාදායකයට සම්බන්ධ වී ඇත්දැයි පරීක්ෂා කළ හැකිය rhs(සමහර විට ප්‍රයෝජනවත් නම් "යළි පිහිටුවීමේ" කේතයක් යැවීම), නමුත් පිටපත් හා හුවමාරු ප්‍රවේශය මඟින් පිටපත්-ඉදිකිරීම්කරුට ආරාධනා කරනු ඇති අතර එය විවෘත කිරීමට ලියා ඇත. පැහැදිලි සොකට් සම්බන්ධතාවයක් පසුව මුල් එක වසා දමන්න. සරල ක්‍රියාවලි විචල්‍ය පිටපතක් වෙනුවට දුරස්ථ ජාල අන්තර්ක්‍රියාකාරිත්වයක් එයින් අදහස් කළ හැකිවා පමණක් නොව, සොකට් සම්පත් හෝ සම්බන්ධතා මත සේවාදායකයා හෝ සේවාදායක සීමාවන් ඉක්මවා යා හැක. (ඇත්ත වශයෙන්ම මෙම පන්තියට ඉතා භයානක අතුරු මුහුණතක් ඇත, නමුත් එය තවත් කාරණයක් ;-P).


4
එයින් කියැවුණේ සොකට් සම්බන්ධතාවය නිදසුනක් පමණි - දෘඩාංග පිරික්සුම / ආරම්භ කිරීම / ක්‍රමාංකනය කිරීම, නූල් හෝ අහඹු සංඛ්‍යා සංචිතයක් ජනනය කිරීම, ඇතැම් ගුප්ත ලේඛනකරණ කාර්යයන්, හැඹිලි, ගොනු පද්ධති පරිලෝකනය, දත්ත සමුදාය වැනි ඕනෑම මිල අධික ආරම්භයක් සඳහා එකම මූලධර්මයම අදාළ වේ. සම්බන්ධතා යනාදිය.
ටෝනි ඩෙල්රෝයි

තවත් එක් (දැවැන්ත) කේතුවක් ඇත. වර්තමාන පිරිවිතරයන්ට අනුව තාක්‍ෂණිකව වස්තුවට චලනය කිරීමේ පැවරුම් ක්‍රියාකරුවෙකු නොමැත! පසුව පංතියක සාමාජිකයෙකු ලෙස භාවිතා කරන්නේ නම්, නව පන්තියට චලනය-ctor ස්වයංක්‍රීයව ජනනය නොවනු ඇත! මුලාශ්‍රය: youtu.be/mYrbivnruYw?t=43m14s
user362515

3
පිටපත් පැවරුම් ක්‍රියාකරුගේ ප්‍රධාන ගැටළුව Clientනම් පැවරුම තහනම් නොවේ.
sbi

ග්‍රාහක උදාහරණයේ දී, පන්තිය පිටපත් කළ නොහැකි ය.
ජෝන් ඉසෙඩ් ලී

25

මෙම පිළිතුර එකතු කිරීමක් හා ඉහත පිළිතුරු වලට සුළු වෙනස් කිරීමක් වැනි ය.

විෂුවල් ස්ටුඩියෝ හි සමහර සංස්කරණ වල (සහ සමහර විට වෙනත් සම්පාදකයින්) දෝෂයක් ඇති අතර එය ඇත්තෙන්ම කරදරකාරී වන අතර තේරුමක් නැත. එබැවින් ඔබ ඔබේ swapක්‍රියාකාරිත්වය මේ ආකාරයෙන් ප්‍රකාශ කරන්නේ නම් / අර්ථ දක්වන්නේ නම් :

friend void swap(A& first, A& second) {

    std::swap(first.size, second.size);
    std::swap(first.arr, second.arr);

}

... ඔබ swapශ්‍රිතය අමතන විට සම්පාදකයා ඔබට කෑගසනු ඇත :

රූප විස්තරය මෙහි ඇතුළත් කරන්න

මෙය යමක් ඇත friendකැඳවීමේ හා කාර්යය thisවස්තුව පරාමිතිය ලෙස සම්මත කර.


මේ සඳහා ක්‍රමයක් නම් friendයතුරු පද භාවිතා නොකිරීම සහ swapශ්‍රිතය නැවත අර්ථ දැක්වීම :

void swap(A& other) {

    std::swap(size, other.size);
    std::swap(arr, other.arr);

}

මෙම අවස්ථාවේදී, ඔබට ඇමතුමක් swapලබා දී ඇතුළට යා otherහැකි අතර එමඟින් සම්පාදකයා සතුටු වේ:

රූප විස්තරය මෙහි ඇතුළත් කරන්න


සියල්ලට පසු, ඔබ වස්තු 2 ක් මාරු කිරීම සඳහා ශ්‍රිතයක් භාවිතා කිරීම අවශ්‍ය නොවේ friend. පරාමිතියක් ලෙස swapඑක් otherවස්තුවක් ඇති සාමාජික ශ්‍රිතයක් සෑදීම තරම්ම අර්ථවත් කරයි .

ඔබට දැනටමත් thisවස්තුවට ප්‍රවේශය ඇත , එබැවින් එය පරාමිතියක් ලෙස සම්මත කිරීම තාක්‍ෂණිකව අතිරික්ත වේ.


1
@GManNickG dropbox.com/s/o1mitwcpxmawcot/example.cpp dropbox.com/s/jrjrn5dh1zez5vy/Untitled.jpg . මෙය සරල කළ අනුවාදයකි. පරාමිතිය friendසමඟ ශ්‍රිතයක් කැඳවන සෑම අවස්ථාවකම දෝෂයක් ඇති බව පෙනේ*this
ඔලෙක්සි

1
SaidGManNickG මම කී පරිදි, එය දෝෂයක් වන අතර අනෙක් පුද්ගලයින්ට හොඳින් ක්‍රියා කළ හැකිය. මට අවශ්‍ය වූයේ මා හා සමාන ගැටලුවක් ඇති සමහර පුද්ගලයින්ට උදව් කිරීමට ය. විෂුවල් ස්ටුඩියෝ 2012 එක්ස්ප්‍රස් සහ 2013 පෙරදසුන යන දෙකින්ම මම මෙය අත්හදා බැලුවෙමි. එය ඉවතට ගිය එකම දෙය නම් මගේ වෙනස් කිරීමයි
ඔලෙක්සි

8
@GManNickG එය සියලු පින්තූර සහ කේත උදාහරණ සමඟ අදහස් දැක්වීමකට නොගැලපේ. මිනිසුන් අවතක්සේරු කළත් කමක් නැහැ, මට විශ්වාසයි එතනම කෙනෙක් එකම දෝෂයක් ඇති බව; මෙම ලිපියේ තොරතුරු ඔවුන්ට අවශ්‍ය දේ පමණක් විය හැකිය.
ඔලෙක්සි

14
මෙය IDE කේත ඉස්මතු කිරීමේ (IntelliSense) දෝෂයක් පමණක් බව සලකන්න ... එය අනතුරු ඇඟවීම් / දෝෂ නොමැතිව හොඳින් සම්පාදනය කරනු ඇත.
අම්රෝ

3
ඔබ දැනටමත් එසේ කර නොමැති නම් (සහ එය නිවැරදි කර නොමැති නම්) කරුණාකර VS දෝෂය මෙහි වාර්තා කරන්න connect.microsoft.com/VisualStudio
Matt

15

ඔබ සී ++ 11-ශෛලීය විබෙදුම්-දැනුවත් බහාලුම් සමඟ ගනුදෙනු කරන විට අනතුරු ඇඟවීමේ වචනයක් එක් කිරීමට මම කැමතියි. හුවමාරු කිරීම සහ පැවරීම සියුම් ලෙස වෙනස් අර්ථකථන ඇත.

Concreteness, අප කන්ටේනර් සලකා බලමු std::vector<T, A>, එහිදී Aයම් අන්ර්සම්බන්ධක විබෙදුම් වර්ගය වන අතර, අප පහත සඳහන් කාර්යයන් සංසන්දනය කරන්නම්:

void fs(std::vector<T, A> & a, std::vector<T, A> & b)
{ 
    a.swap(b);
    b.clear(); // not important what you do with b
}

void fm(std::vector<T, A> & a, std::vector<T, A> & b)
{
    a = std::move(b);
}

කාර්යයන් දෙකෙහිම අරමුණ fsසහ මුලින් තිබූ රාජ්‍යය fmලබා දීමයි . කෙසේ වෙතත්, සැඟවුණු ප්‍රශ්නයක් තිබේ: කුමක් සිදුවේද ? පිළිතුර: එය රඳා පවතී. අපි ලියමු .aba.get_allocator() != b.get_allocator()AT = std::allocator_traits<A>

  • එසේ AT::propagate_on_container_move_assignmentනම් std::true_type, fmප්‍රතිපාදකයාගේ aඅගය සමඟ නැවත පවරන්න b.get_allocator(), එසේ නොමැති නම් එය නොකෙරේ, සහ aඑහි මුල් විබෙදුම දිගටම භාවිතා කරයි. එවැනි අවස්ථාවකදී, දත්ත මූලද්‍රව්‍යයන් වෙන වෙනම හුවමාරු කර ගත යුතුය, මන්ද ගබඩා කිරීම aහා bඅනුකූල නොවේ.

  • එසේ AT::propagate_on_container_swapනම් std::true_type, fsඅපේක්ෂිත ආකාරයට දත්ත සහ විබෙදුම් දෙකම මාරු කරයි.

  • නම් AT::propagate_on_container_swapවේ std::false_type, ඉන් පසුව අපි ගතික චෙක්පත අවශ්යයි.

    • එසේ නම් a.get_allocator() == b.get_allocator(), බහාලුම් දෙක අනුකූල ගබඩාවක් භාවිතා කරන අතර, හුවමාරු කර ගැනීම සුපුරුදු පරිදි සිදු වේ.
    • කෙසේ වෙතත්, a.get_allocator() != b.get_allocator()වැඩසටහනට නිර්වචනය නොකළ හැසිරීම් තිබේ නම් (cf. [container.requirements.general / 8].

මෙහි ප්‍රති shot ලය වනුයේ ඔබේ බහාලුම රාජ්‍ය විබෙදුම්කරුවන්ට සහය දැක්වීම ආරම්භ කළ විගස හුවමාරු කිරීම සී ++ 11 හි සුළු නොවන ක්‍රියාවක් බවට පත්වීමයි. එය තරමක් “දියුණු භාවිත නඩුවකි”, නමුත් එය සම්පුර්ණයෙන්ම කළ නොහැක්කකි, මන්දයත් චලනය ප්‍රශස්තිකරණය සාමාන්‍යයෙන් සිත්ගන්නාසුළු වන්නේ ඔබේ පන්තිය සම්පතක් කළමනාකරණය කළ පසු පමණක් වන අතර මතකය වඩාත් ජනප්‍රිය සම්පතකි.

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.