C ++ හි දර්ශක විචල්‍යයක් සහ යොමු විචල්‍යයක් අතර ඇති වෙනස්කම් මොනවාද?


3271

යොමුව සින්ටැක්ටික් සීනි බව මම දනිමි, එබැවින් කේතය කියවීමට හා ලිවීමට පහසුය.

නමුත් වෙනස්කම් මොනවාද?


102
මා සිතන්නේ ලක්ෂ්‍යය 2 විය යුත්තේ "දර්ශකයක් NULL වීමට ඉඩ දී ඇති නමුත් යොමු කිරීමක් නොවේ. විකෘති කේතයකට පමණක් NULL යොමු කිරීමක් කළ හැකි අතර එහි හැසිරීම නිර්වචනය කර නැත."
මාර්ක් රැන්සම්

20
දර්ශකයන් යනු තවත් වර්ගයක වස්තුවක් වන අතර C ++ හි ඇති ඕනෑම වස්තුවක් මෙන් ඒවා විචල්‍යයක් විය හැකිය. අනෙක් අතට යොමු කිරීම් කිසි විටෙකත් වස්තු නොවේ, විචල්යයන් පමණි .
කෙරෙක් එස් බී

20
මෙය අනතුරු ඇඟවීමකින් තොරව සම්පාදනය කරයි: int &x = *(int*)0;gcc මත. යොමු කිරීම ඇත්ත වශයෙන්ම NULL වෙත යොමු කළ හැකිය.
කැල්මේරියස්

21
යොමුව විචල්‍ය අන්වර්ථයකි
Khaled.K

21
මම කැමතියි පළමු වාක්‍යය මුළුමනින්ම වැරැද්දක් වන්නේ කෙසේද කියා. යොමුවලට ඔවුන්ගේම අර්ථකථන ඇත.
කක්ෂයේ සැහැල්ලු ධාවන තරඟ

Answers:


1710
  1. දර්ශකයක් නැවත පැවරිය හැකිය:

    int x = 5;
    int y = 6;
    int *p;
    p = &x;
    p = &y;
    *p = 10;
    assert(x == 5);
    assert(y == 10);

    යොමු කිරීමක් කළ නොහැකි අතර එය ආරම්භයේදී පැවරිය යුතුය:

    int x = 5;
    int y = 6;
    int &r = x;
  2. දර්ශකයට එහි මතක ලිපිනය සහ ප්‍රමාණය (x86 මත බයිට් 4) ඇත, නමුත් යොමු කිරීමක් එකම මතක ලිපිනය (මුල් විචල්‍යය සමඟ) බෙදා ගන්නා අතර තොගයේ යම් ඉඩක් ගනී. යොමුවකට මුල් විචල්‍යයට සමාන ලිපිනයක් ඇති බැවින්, එකම විචල්‍යයේ වෙනත් නමක් ලෙස යොමු කිරීමක් සිතීම ආරක්ෂිත වේ. සටහන: තොගයේ හෝ ගොඩවල තිබිය හැකි දර්ශකය කුමක්ද? ඩිටෝ යොමු කිරීමක්. මෙම ප්‍රකාශයේ මගේ ප්‍රකාශය වන්නේ දර්ශකයක් තොගයට යොමු කළ යුතු බව නොවේ. දර්ශකය යනු මතක ලිපිනයක් ඇති විචල්‍යයකි. මෙම විචල්‍යය තොගයේ ඇත. යොමුවකට තොගයේ තමන්ගේම ඉඩක් ඇති හෙයින් සහ ලිපිනය විචල්‍යයට සමාන බැවින් එය යොමු කරයි. ගොඩවල් එදිරිව ගොඩවල් මත තවත්. මෙයින් ගම්‍ය වන්නේ සම්පාදකයා ඔබට නොකියන යොමුවක සැබෑ ලිපිනයක් ඇති බවයි.

    int x = 0;
    int &r = x;
    int *p = &x;
    int *p2 = &r;
    assert(p == p2);
  3. ඔබට අමතර මට්ටමේ අවිනිශ්චිතතාවයන් ලබා දෙන දර්ශකයන්ට දර්ශක සිට දර්ශක දක්වා විය හැකිය. යොමු දැක්වීම් ඉදිරිපත් කරන්නේ එක් මට්ටමේ අවිනිශ්චිතතාවයක් පමණි.

    int x = 0;
    int y = 0;
    int *p = &x;
    int *q = &y;
    int **pp = &p;
    pp = &q;//*pp = q
    **pp = 4;
    assert(y == 4);
    assert(x == 0);
  4. nullptrයොමු කිරීමක් කළ නොහැකි අතර, දර්ශකයක් කෙලින්ම පැවරිය හැකිය. ඔබ ප්‍රමාණවත් ලෙස උත්සාහ කර, කෙසේ දැයි ඔබ දන්නේ නම්, ඔබට යොමු කිරීමක ලිපිනය සෑදිය හැකිය nullptr. ඒ හා සමානව, ඔබ ප්‍රමාණවත් ලෙස උත්සාහ කළහොත්, ඔබට දර්ශකයක් වෙත යොමු කිරීමක් කළ හැකි අතර, එම සඳහනෙහි අඩංගු nullptrවිය හැකිය .

    int *p = nullptr;
    int &r = nullptr; <--- compiling error
    int &r = *p;  <--- likely no compiling error, especially if the nullptr is hidden behind a function call, yet it refers to a non-existent int at address 0
  5. දර්ශකයන්ට අරාව හරහා නැවත යෙදිය හැකිය; ඔබට ++දර්ශකයක් යොමු කරන ඊළඟ අයිතමය + 4වෙත යාමට සහ 5 වන අංගයට යාමට භාවිතා කළ හැකිය. දර්ශකය පෙන්වා දෙන වස්තුව කොතරම් විශාල වුවත් මෙය වැදගත් නොවේ.

  6. එය යොමු *කරන මතක ස්ථානයට ප්‍රවේශ වීම සඳහා දර්ශකයක් අවලංගු කළ යුතු අතර, යොමු කිරීමක් කෙලින්ම භාවිතා කළ හැකිය. පංතියකට / ව්‍යුහයකට දර්ශකයක් ->එහි සාමාජිකයින්ට ප්‍රවේශ වීම සඳහා භාවිතා කරන අතර යොමු කිරීමක් භාවිතා කරයි ..

  7. යොමු දැක්වීම් අරාවකට පුරවා ගත නොහැකි අතර, දර්ශකයන් විය හැකි අතර (පරිශීලක it ලිට්බ් විසින් සඳහන් කර ඇත)

  8. නිරන්තර යොමු කිරීම් තාවකාලික වලට බැඳිය හැකිය. දර්ශකයන්ට නොහැක (කිසියම් අවිනිශ්චිතතාවයකින් තොරව):

    const int &x = int(12); //legal C++
    int *y = &int(12); //illegal to dereference a temporary.

    මෙය const&තර්ක ලැයිස්තුවේ සහ වෙනත් දේ සඳහා ආරක්ෂිත වේ.


23
... නමුත් NULL අවලංගු කිරීම නිර්වචනය කර නැත. උදාහරණයක් ලෙස, යොමු කිරීමක් NULL දැයි ඔබට පරීක්ෂා කළ නොහැක (උදා: & ref == NULL).
පැට් නොට්ස්

69
අංක 2 සත්‍ය නොවේ . යොමු කිරීමක් යනු “එකම විචල්‍යයේ තවත් නමක්” නොවේ. යොමු කිරීම් වලට සමාන ආකාරයකින් පන්තිවල ගබඩා කර ඇති කාර්යයන් වෙත යොමු කළ හැකිය. ඒවා පෙන්වා දෙන විචල්‍යයන්ගෙන් ස්වාධීනව පවතී.
ඩෙරෙක් පාක්

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

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

38
තවත් වැදගත් වෙනසක්: යොමුව අරාවකට පුරවා ගත නොහැක
ජොහැන්නස් ෂෝබ් - litb

385

C ++ යොමු කිරීම යනු කුමක්ද ( C ක්‍රමලේඛකයින් සඳහා )

සඳහනක් ලෙස කල්පනා කළ හැකි නිරන්තර අවධානය යොමුකළ සම්පාදකවරයා වන අයදුම් කරනු ඇත (! නියත අගය කිරීමට අවධානය යොමුකළ සමඟ පටලවා නොගත) ස්වයංක්රීය indirection සමග, එනම් *ඔබ වෙනුවෙන් ක්රියාකරු.

සියලුම යොමු කිරීම් ශුන්‍ය නොවන අගයකින් ආරම්භ කළ යුතුය, නැතහොත් සම්පාදනය අසාර්ථක වනු ඇත. විමර්ශනයක ලිපිනය ලබා ගත නොහැක - ලිපින ක්‍රියාකරු ඒ වෙනුවට යොමු කළ අගයෙහි ලිපිනය නැවත ලබා දෙනු ඇත - යොමු කිරීම් මත අංක ගණිතය කිරීමට ද නොහැකිය.

C ක්‍රමලේඛකයින් C ++ යොමු කිරීම් වලට අකමැති විය හැකි බැවින් එය අවිනිශ්චිතතාවයක් සිදු වූ විට හෝ ශ්‍රිත අත්සන් දෙස නොබලා තර්කයක් වටිනාකමින් හෝ දර්ශකයකින් සම්මත වුවහොත් එය තවදුරටත් පැහැදිලි නොවනු ඇත.

C ++ ක්‍රමලේඛකයින් අනාරක්ෂිත යැයි සලකන බැවින් දර්ශක භාවිතා කිරීමට අකමැති විය හැකිය - බොහෝ සුළු කාරණා හැරුණු විට නියත දර්ශකයන්ට වඩා යොමු කිරීම් සැබවින්ම ආරක්ෂිත නොවේ - ස්වයංක්‍රීය නිරෝධනය කිරීමේ පහසුව සහ වෙනස් අර්ථකථන අර්ථයක් ඇත.

C ++ නිති අසන ප්‍රශ්න වලින් පහත ප්‍රකාශය සලකා බලන්න :

යටින් පවතින assembly භාෂාවෙන් ලිපිනයක් භාවිතා කර සඳහනක් බොහෝ විට ක්රියාත්මක වුවත්, කරුණාකර නොවන වස්තුවක් සඳහා මාර ලස්සන පහිටුම් දක්වනය ලෙස සඳහනක් හිතන්න. යොමු කිරීම යනු වස්තුවයි. එය වස්තුවට දර්ශකයක් හෝ වස්තුවක පිටපතක් නොවේ. එය වේ වස්තුව.

නමුත් යොමු කිරීමක් ඇත්ත වශයෙන්ම වස්තුව නම්, අන්තරාදායක යොමු කිරීම් තිබිය හැක්කේ කෙසේද? කළමනාකරණය නොකළ භාෂාවල, යොමු කිරීම් දර්ශකයන්ට වඩා 'ආරක්ෂිත' වීම කළ නොහැක්කකි - සාමාන්‍යයෙන් විෂය පථයේ සීමාවන් හරහා අන්වර්ථ අගයන් විශ්වාසදායක ලෙස වෙනස් කිරීමට ක්‍රමයක් නොමැත!

මා C ++ යොමු ප්‍රයෝජනවත් යැයි සලකන්නේ ඇයි

සී පසුබිම සිට පැමිණෙන, C ++ යොමු තරමක් මෝඩ සංකල්පය වගේ විය හැක, නමුත් එක තවමත් සූචක හැකි නම් වෙනුවට ඔවුන් භාවිතා කළ යුතු: ස්වයංක්රීය indirection වේ පහසු, සහ සමඟ කටයුතු කරන විට යොමු විශේෂයෙන්ම ප්රයෝජනවත් වී RAII - නිසා ඕනෑම දකින්නේ ආරක්ෂාව නමුත් වාසිය, නමුත් ඔවුන් මුග්ධ කේත ලිවීම අඩු අමුතු නිසා.

RAII යනු C ++ හි කේන්ද්‍රීය සංකල්පවලින් එකකි, නමුත් එය අර්ථකථන පිටපත් කිරීම සමඟ සුළු වශයෙන් අන්තර්ක්‍රියා කරයි. පිටපත් කිරීමකට සම්බන්ධ නොවන බැවින් වස්තු යොමු කිරීම මඟින් මෙම ගැටළු මඟහරවා ගත හැකිය. භාෂාවේ යොමු කිරීම් නොතිබුනේ නම්, ඒ වෙනුවට ඔබට දර්ශක භාවිතා කිරීමට සිදුවනු ඇත, ඒවා භාවිතා කිරීමට වඩා කරදරකාරී වන අතර එමඟින් භාෂා සැලසුම් මූලධර්මය උල්ලං ting නය කරමින් විකල්පයන්ට වඩා හොඳ-ප්‍රායෝගික විසඳුම පහසු විය යුතුය.


17
r ක්‍රිස්: නැත, ඔබට ස්වයංක්‍රීය විචල්‍යයක් යොමු කිරීමෙන් ආපසු ලබා දීමෙන් අනතුරුදායක යොමු කිරීමක් ලබා ගත හැකිය.
බෙන් වොයිග්ට්

12
r ක්‍රිස්: සම්පාදකයෙකුට සාමාන්‍ය නඩුවේදී හඳුනාගත නොහැකි තරම්ය. පංති සාමාජික විචල්‍යයකට යොමු කිරීමක් සපයන සාමාජික ශ්‍රිතයක් සලකා බලන්න: එය ආරක්ෂිත වන අතර එය සම්පාදකයා විසින් තහනම් නොකළ යුතුය. එවිට එම පන්තියේ ස්වයංක්‍රීය නිදසුනක් ඇති ඇමතුම්කරුවෙකු එම සාමාජික ශ්‍රිතය අමතා යොමු කිරීම ලබා දෙයි. ප්‍රෙස්ටෝ: කරකවන යොමුව. ඔව්, එය කරදරයක් වනු ඇත, ක්‍රිස්: ඒක තමයි මගේ අදහස. බොහෝ අය කියා සිටින්නේ දර්ශකයන්ට වඩා යොමු කිරීම්වල වාසියක් වන්නේ යොමු කිරීම් සැමවිටම වලංගු වන නමුත් එය එසේ නොවේ.
බෙන් වොයිග්ට්

4
r ක්‍රිස්: නැත, ස්වයංක්‍රීය ගබඩා කාල සීමාවක් ඇති වස්තුවක් පිළිබඳ සඳහනක් තාවකාලික වස්තුවකට වඩා බෙහෙවින් වෙනස් ය. කෙසේ වෙතත්, මම ඔබට අවලංගු යොමු කිරීමක් ලබා ගත හැක්කේ අවලංගු දර්ශකයක් අවලංගු කිරීමෙන් පමණක් යැයි ඔබේ ප්‍රකාශයට ප්‍රති-උදාහරණයක් සපයමින් සිටියෙමි. ක්‍රිස්ටෝෆ් නිවැරදියි - යොමු කිරීම් දර්ශකයන්ට වඩා ආරක්ෂිත නොවේ, යොමු කිරීම් පමණක් භාවිතා කරන වැඩසටහනකට තවමත් වර්ගයේ ආරක්ෂාව බිඳ දැමිය හැකිය.
බෙන් වොයිග්ට්

7
යොමු කිරීම් එක්තරා ආකාරයක දර්ශකයක් නොවේ. ඒවා දැනට පවතින වස්තුවකට නව නමකි.
කැට්ෆයිව්

18
at කැට්ෆයිව්: ඔබ භාෂා අර්ථකථන අනුව ගියහොත් සත්‍යය, ඔබ ඇත්ත වශයෙන්ම ක්‍රියාත්මක කිරීම දෙස බැලුවහොත් සත්‍ය නොවේ; සී ++ යනු ඊට වඩා 'ඉන්ද්‍රජාලික' භාෂාවක් වන අතර, ඔබ මැජික් යොමු වලින් ඉවත් කළහොත්, ඔබ දර්ශකය සමඟ අවසන් වේ
ක්‍රිස්ටෝෆ්

191

ඔබට සැබවින්ම ව්‍යාකූල වීමට අවශ්‍ය නම්, ඔබට දර්ශකයක් සමඟ කළ නොහැකි සඳහනක් සමඟ ඔබට කළ හැකි එක් දෙයක් තිබේ: තාවකාලික වස්තුවක ආයු කාලය දීර් extend කරන්න. C ++ හි ඔබ තාවකාලික වස්තුවකට සංයුක්ත යොමු කිරීමක් බන්ධනය කරන්නේ නම්, එම වස්තුවේ ආයු කාලය යොමු වීමේ ආයු කාලය බවට පත්වේ.

std::string s1 = "123";
std::string s2 = "456";

std::string s3_copy = s1 + s2;
const std::string& s3_reference = s1 + s2;

මෙම උදාහරණයේ දී s3_copy සංයුක්තතාවයේ ප්‍රති result ලයක් වන තාවකාලික වස්තුව පිටපත් කරයි. සාරය අනුව s3_reference තාවකාලික වස්තුව බවට පත්වේ. එය සැබවින්ම තාවකාලික වස්තුවක් සඳහා යොමු කිරීමකි.

ඔබ මෙය නොමැතිව උත්සාහ කළහොත් constඑය සම්පාදනය කිරීමට අසමත් විය යුතුය. ඔබට තාවකාලික වස්තුවකට නොනවතින සඳහනක් බැඳ තැබිය නොහැක, එම කාරණය සඳහා එහි ලිපිනය ගත නොහැක.


5
නමුත් මේ සඳහා භාවිතා කිරීමේ අවස්ථාව කුමක්ද?
අහමඩ් මුෂ්තාක්

20
හොඳයි, s3_copy තාවකාලික එකක් නිර්මාණය කර එය පිටපත් කර s3_copy බවට පත් කරන අතර s3_reference සෘජුවම තාවකාලික භාවිතා කරයි. පළමු අවස්ථාවේ දී පිටපත් ඉදිකිරීම මග හැරීමට සම්පාදකයාට අවසර දී ඇති ප්‍රතිලාභ අගය ප්‍රශස්තිකරණය දෙස බැලිය යුතුය.
මැට් මිල

6
ig ඩිජිටල් සර්ජන්: එහි ඇති මැජික් තරමක් බලවත් ය. වස්තු ආයු කාලය දීර් is වන්නේ const &බන්ධනයේ සත්‍යතාවයෙන් වන අතර , යොමු කිරීම විෂය පථයෙන් බැහැර වූ විට පමණක් සත්‍ය යොමු කරන ලද වර්ගය විනාශ කරන්නා ලෙස හැඳින්වේ (යොමු වර්ගයට සාපේක්ෂව එය පදනමක් විය හැකිය). එය යොමු කිරීමක් බැවින්, ඒ අතර කිසිදු පෙත්තක් සිදු නොවේ.
ඩේවිඩ් රොඩ්‍රිගුස් - ඩ්‍රිබියස්

9
C ++ 11 සඳහා යාවත්කාලීන කිරීම: අවසාන වාක්‍යය කියවිය යුත්තේ "ඔබට තාවකාලික නොවන සංයුක්ත නොවන අගයක් යොමු කළ නොහැක ", මන්දයත් ඔබට තාවකාලික නොවන නියත අගයක් යොමු කළ හැකි අතර එයට ජීවිත කාලය පුරාම පවතින හැසිරීමක් ඇත.
ඔක්ටාලිස්ට්

4
H අහමඩ් මුෂ්තාක්: මෙහි ප්‍රධාන භාවිතය ව්‍යුත්පන්න පංති වේ. උරුමයක් නොමැති නම්, ඔබට වටිනාකම් අර්ථකථන භාවිතා කළ හැකිය, එය RVO / චලනය ඉදිකිරීම හේතුවෙන් ලාභදායී හෝ නොමිලේ වනු ඇත. එහෙත් ඔබ නම්, Animal x = fast ? getHare() : getTortoise()එසේ නම් xසම්භාව්ය යසිකා, ගැටළුව, මුහුණ දෙනු ඇත අතර, Animal& x = ...නිවැරදිව වැඩ කරනු ඇත.
ආතර් ටකා

128

මීට අමතරව සින්ටැක්ටික් සීනි සිට, අදාල නම් වේ constදර්ශකයක් ( නැති වූ පෙන්නුම් කරන්නක් const). ඔබ විමර්ශන විචල්‍යය ප්‍රකාශ කරන විට එය යොමු කරන දේ ඔබ විසින් ස්ථාපිත කළ යුතු අතර ඔබට පසුව එය වෙනස් කළ නොහැක.

යාවත්කාලීන කිරීම: දැන් මම ඒ ගැන තවත් සිතන විට වැදගත් වෙනසක් ඇත.

කොන්ස්ට් පොයින්ටරයක ඉලක්කය එහි ලිපිනය ගෙන කොන්ස්ට් කාස්ට් භාවිතා කිරීමෙන් ප්‍රතිස්ථාපනය කළ හැකිය.

යොමුවක ඉලක්කය යූබී හි කිසිදු ආකාරයකින් ප්‍රතිස්ථාපනය කළ නොහැක.

මෙය සම්පාදකයාට යොමු කිරීමක් මත වඩාත් ප්‍රශස්තිකරණය කිරීමට අවසර දිය යුතුය.


8
මම හිතන්නේ මේ දක්වා ඇති හොඳම පිළිතුර මෙයයි. තවත් සමහරු විවිධ තිරිසනුන් මෙන් යොමු කිරීම් සහ දර්ශකයන් ගැන කතා කරති. එය දේවල් පහසු නැත. මම සෑම විටම යොමු කර T* constඇත්තේ වෙනස් සින්ටැක්ටික් සීනි සහිත (එය සිදුවන්නේ * සහ ඔබේ කේතයෙන් බොහෝ දේ ඉවත් කිරීමට ය).
කාලෝ වුඩ්

2
"කොන්ස්ට් පොයින්ටරයක ඉලක්කය එහි ලිපිනය ගෙන කොන්ස්ට් කාස්ට් භාවිතා කිරීමෙන් ප්‍රතිස්ථාපනය කළ හැකිය." එසේ කිරීම නිර්වචනය නොකළ හැසිරීමකි. වැඩි විස්තර සඳහා stackoverflow.com/questions/25209838/… බලන්න.
dgnuff

1
යොමු යොමු කිරීමක් හෝ සංයුක්ත දර්ශකයක වටිනාකම (හෝ ඕනෑම පරිමාණ පරිමාණයක්) වෙනස් කිරීමට උත්සාහ කිරීම සමානාත්මතාවය නීති විරෝධී ය. ඔබට කළ හැකි දේ: ව්‍යංග පරිවර්තනය මගින් එකතු කරන ලද සංයුක්ත සුදුසුකමක් ඉවත් කරන්න: int i; int const *pci = &i; /* implicit conv to const int* */ int *pi = const_cast<int*>(pci);හරි.
කුතුහලයෙන්

1
මෙහි වෙනස UB හා වචනාර්ථයෙන් කළ නොහැකි ය. C ++ හි කිසිදු වාක්‍ය ඛණ්ඩයක් නොමැති අතර එය යොමු ලක්ෂ්‍යයන් වෙනස් කිරීමට ඔබට ඉඩ සලසයි.

කළ නොහැකි, අමාරු නොවේ, ඔබට එම යොමු කිරීම ආදර්ශනය කරන දර්ශකයේ මතක ප්‍රදේශයට ප්‍රවේශ වී එහි අන්තර්ගතය වෙනස් කළ හැකිය. එය නිසැකවම කළ හැකිය.
නිකොලස් බෝස්කට්

126

ජනප්‍රිය මතයට පටහැනිව, NULL ලෙස යොමු දැක්වීමක් කළ හැකිය.

int * p = NULL;
int & r = *p;
r = 1;  // crash! (if you're lucky)

ඇත්ත වශයෙන්ම, යොමු කිරීමක් සමඟ එය කිරීම වඩා දුෂ්කර ය - නමුත් ඔබ එය කළමනාකරණය කරන්නේ නම්, ඔබ එය සොයා ගැනීමට උත්සාහ කරමින් ඔබේ කොණ්ඩය ඉරා දමනු ඇත. C ++ හි යොමු කිරීම් සහජයෙන්ම ආරක්ෂිත නොවේ !

තාක්ෂණික වශයෙන් මෙය අවලංගු යොමු කිරීමක් මිස ශුන්‍ය යොමු කිරීමක් නොවේ. ඔබ වෙනත් භාෂාවලින් සොයාගත හැකි පරිදි C ++ සංකල්පයක් ලෙස ශුන්‍ය යොමු කිරීම් සඳහා සහාය නොදක්වයි. වෙනත් අවලංගු යොමු කිරීම් ද තිබේ. ඕනෑම අවලංගු සඳහනක් අවලංගු දර්ශකයක් භාවිතා කරන ආකාරයටම, නිර්වචනය නොකළ හැසිරීමේ අවතාරය මතු කරයි .

සත්‍ය දෝෂය ඇත්තේ යොමු කිරීමකට පැවරීමට පෙර NULL දර්ශකය විරූපණය කිරීමයි. නමුත් එම කොන්දේසිය මත කිසියම් දෝෂයක් ජනනය කරන කිසිදු සම්පාදකයෙකු ගැන මම නොදනිමි - දෝෂය කේතය තුළ තව දුරටත් ව්‍යාප්ත වේ. එයයි මෙම ගැටලුව මෙතරම් ද්‍රෝහී වන්නේ. බොහෝ විට, ඔබ NULL දර්ශකයක් අවලංගු කළහොත්, ඔබ එම ස්ථානයේදීම කඩා වැටෙන අතර එය සොයා ගැනීමට බොහෝ නිදොස් කිරීම් අවශ්‍ය නොවේ.

ඉහත මගේ උදාහරණය කෙටියි. මෙන්න වඩාත් සැබෑ ලෝක උදාහරණයක්.

class MyClass
{
    ...
    virtual void DoSomething(int,int,int,int,int);
};

void Foo(const MyClass & bar)
{
    ...
    bar.DoSomething(i1,i2,i3,i4,i5);  // crash occurs here due to memory access violation - obvious why?
}

MyClass * GetInstance()
{
    if (somecondition)
        return NULL;
    ...
}

MyClass * p = GetInstance();
Foo(*p);

ශුන්‍ය යොමු කිරීමක් ලබා ගත හැකි එකම ක්‍රමය විකෘති කේතයක් බව නැවත අවධාරණය කිරීමට මට අවශ්‍යය, ඔබ එය ලබා ගත් පසු ඔබට නිර්වචනය නොකළ හැසිරීමක් ලැබේ. එය කිසි විටෙකත් එය ශූන්ය පරිශීලනය සඳහා පරීක්ෂා කිරීමට තේරුමක්; උදාහරණයක් ලෙස ඔබට උත්සාහ කළ හැකි if(&bar==NULL)...නමුත් සම්පාදකයා ප්‍රකාශය නොපවතින ලෙස ප්‍රශස්තිකරණය කරයි! වලංගු යොමු කිරීමක් කිසි විටෙකත් NULL විය නොහැක, එබැවින් සම්පාදකයාගේ දෘෂ්ටි කෝණයෙන් සැසඳීම සැමවිටම අසත්‍ය වන අතර, ifවගන්තිය මළ කේතයක් ලෙස ඉවත් කිරීම නොමිලේ - මෙය නිර්වචනය නොකළ හැසිරීමේ සාරයයි.

කරදරයකින් තොරව සිටීමට සුදුසුම ක්‍රමය නම්, යොමු කිරීමක් නිර්මාණය කිරීම සඳහා NULL දර්ශකයක් අවලංගු කිරීමෙන් වළකින්න. මෙය ඉටු කිරීම සඳහා ස්වයංක්‍රීය ක්‍රමයක් මෙන්න.

template<typename T>
T& deref(T* p)
{
    if (p == NULL)
        throw std::invalid_argument(std::string("NULL reference"));
    return *p;
}

MyClass * p = GetInstance();
Foo(deref(p));

වඩා හොඳ ලිවීමේ කුසලතා ඇති අයෙකුගෙන් මෙම ගැටළුව පැරණි ලෙස බැලීමට, ජිම් හයිස්ලොප් සහ ඔසු සූටර්ගේ ශූන්‍ය යොමු බලන්න .

ශුන්‍ය දර්ශකයක් අවලංගු කිරීමේ අන්තරායන් පිළිබඳ තවත් උදාහරණයක් සඳහා රේමන්ඩ් චෙන් විසින් වෙනත් වේදිකාවක් වෙත කේතය ගෙනයාමට උත්සාහ කරන විට නිර්වචනය නොකළ හැසිරීම හෙළිදරව් කිරීම බලන්න .


64
සැක සහිත කේතයේ නිර්වචනය නොකළ හැසිරීම අඩංගු වේ. තාක්ෂණික වශයෙන්, ඔබට එය ශුන්‍ය දර්ශකයක් සමඟ සැකසීමට හැර කිසිවක් කළ නොහැක. ඔබේ වැඩසටහන නිර්වචනය නොකළ හැසිරීමට ආයාචනා කළ පසු, ඔබ ලොකු ලොක්කාට නිරූපණයක් ලබා දෙන තුරු එය නිවැරදිව වැඩ කිරීම වැනි ඕනෑම දෙයක් කළ හැකිය.
කීත් බී

10
සලකුණට වලංගු තර්කයක් ඇත. දර්ශකයක් NULL විය හැකි අතර ඒ සඳහා ඔබ විසින් පරීක්ෂා කළ යුතුය යන තර්කය ද සත්‍ය නොවේ: ශ්‍රිතයකට NULL නොවන බව ඔබ කියන්නේ නම්, අමතන්නාට එය කළ යුතුය. එබැවින් අමතන්නා එසේ නොකළහොත් ඔහු නිර්වචනය නොකළ හැසිරීමක් සිදු කරයි. සලකුණ නරක සඳහනක් කළාක් මෙන්
ජොහැන්නස් ෂෝබ් - litb

14
විස්තරය වැරදිය. මෙම කේතය NULL ලෙස යොමු කිරීමක් නිර්මාණය කිරීමට හෝ නොවීමට ඉඩ ඇත. එහි හැසිරීම නිර්වචනය කර නැත. එය පරිපූර්ණ වලංගු යොමු කිරීමක් නිර්මාණය කරයි. කිසියම් සඳහනක් නිර්මාණය කිරීමට එය අසමත් විය හැකිය.
ඩේවිඩ් ෂ්වාට්ස්

8
Av ඩේවිඩ් ෂ්වාට්ස්, මම කතා කරන්නේ ප්‍රමිතියට අනුව දේවල් කළ යුතු ආකාරය ගැන නම්, ඔබ නිවැරදි වනු ඇත. නමුත් එම තියෙන්නේ නැහැ මම මේ ගැන කතා කරන්නේ කුමක් - මම ඉතා ජනප්රිය සම්පාදක සමග සැබෑ නිරීක්ෂිත හැසිරීම ගැන කතා, හා වර්තන කරනවා ඇත දේ සාමාන්ය සම්පාදනය සහ CPU ආකෘතීන් මගේ දැනුම මත පදනම් බොහෝ විට සිදුවන්නේ කියලා. යොමු කිරීම් ආරක්ෂිත බැවින් ඒවා යොමු කිරීම් වඩා උසස් යැයි ඔබ විශ්වාස කරන්නේ නම් සහ යොමු කිරීම් නරක යැයි නොසිතන්නේ නම්, මා සිටි ආකාරයටම යම් දවසක ඔබ සරල ගැටලුවකට ගොදුරු වනු ඇත.
මාර්ක් රැන්සම්

7
ශුන්‍ය දර්ශකයක් අවලංගු කිරීම වැරදිය. එය කරන ඕනෑම වැඩසටහනක්, යොමු කිරීමක් ආරම්භ කිරීම පවා වැරදිය. ඔබ දර්ශකයකින් යොමු කිරීමක් ආරම්භ කරන්නේ නම්, දර්ශකය වලංගු දැයි ඔබ නිතරම පරීක්ෂා කළ යුතුය. මෙය සාර්ථක වුව ද, නොපවතින වස්තුව යොමු කිරීම සඳහා යොමු කිරීම අතහැර දමා ඕනෑම වේලාවක යටින් පවතින වස්තුව මකා දැමිය හැකිය, නේද? ඔබ කියන්නේ හොඳ දේවල්. මම හිතන්නේ මෙහි ඇති සැබෑ ගැටළුව නම්, ඔබ එකක් දකින විට “ශුන්‍යතාවය” සඳහා යොමු කිරීම අවශ්‍ය නොවන අතර දර්ශකය අවම වශයෙන් තහවුරු කළ යුතුය.
t0rakka

115

ඔබට වඩාත්ම වැදගත් කොටස අමතක විය:

පොයින්ටර්ස් සමඟ ->
සාමාජික ප්‍රවේශය පරිශීලක යොමු ප්‍රවේශය සමඟ සාමාජික ප්‍රවේශය භාවිතා කරයි.

foo.barවන පැහැදිලිව වඩා උසස් foo->barකරන ආකාරයට vi වන පැහැදිලිව වඩා උසස් හැරදමයි :-)


4
R ඔරියන් එඩ්වර්ඩ්ස්> පොයින්ටර්ස් භාවිතයෙන් සාමාජික ප්‍රවේශය - >> පරිශීලක යොමු ප්‍රවේශය සමඟ ප්‍රවේශය. මෙය 100% සත්‍ය නොවේ. ඔබට දර්ශකයක් වෙත යොමු කිරීමක් කළ හැකිය. මෙම අවස්ථාවෙහිදී, ඔබ ඊළඟට -> struct Node {Node * භාවිතා කරමින් යොමු කරන ලද දර්ශකයේ සාමාජිකයින්ට ප්‍රවේශ වනු ඇත; }; නෝඩ් * පළමුව; // p යනු දර්ශක අවලංගු foo (Node * & p) වෙත යොමු කිරීමකි {p-> next = first; } නෝඩ් * බාර් = නව නෝඩ්; foo (බාර්); - OP: ඔබ අගයන් සහ අගයන් පිළිබඳ සංකල්ප ගැන හුරුපුරුදුද?

3
ස්මාර්ට් පොයින්ටර්ස් දෙකම ඇත. (ස්මාර්ට් පොයින්ටර් පන්තියේ ක්‍රම) සහ -> (යටින් පවතින වර්ගය පිළිබඳ ක්‍රම).
ජේබීආර් විල්කින්සන්

1
6 user6105 ඔරියන් එඩ්වර්ඩ්ස් ප්‍රකාශය ඇත්ත වශයෙන්ම 100% සත්‍ය වේ. "යොමු කරන ලද දර්ශකයේ සාමාජිකයින්ට ප්‍රවේශ වන්න" දර්ශකයට සාමාජිකයන් නොමැත. දර්ශකයට යොමු වන වස්තුවට සාමාජිකයන් සිටින අතර, ඒවාට ප්‍රවේශ වීම හරියටම ->දර්ශකය වෙත යොමු කිරීම සඳහා සපයයි.
මැක්ස් ට ru ක්සා

1
ඇයි එය .සහ ->vi සහ emacs සමඟ යම් සම්බන්ධයක් තිබේ :)
artm

10
@artM - එය විහිළුවක් වූ අතර බොහෝ විට ස්වදේශීය නොවන ඉංග්‍රීසි කථිකයින්ට තේරුමක් නැත. මාගේ කණගාටුව. පැහැදිලි කිරීම සඳහා, vi ඊමාක් වලට වඩා හොඳ ද යන්න සම්පූර්ණයෙන්ම ආත්මීය ය. සමහර අය vi වඩා උසස් යැයි සිතන අතර තවත් සමහරු සිතන්නේ ඊට ප්‍රතිවිරුද්ධ දෙයයි. ඒ හා සමානව, භාවිතා .කිරීමට වඩා හොඳ යැයි මම සිතමි ->, නමුත් vi vs emacs මෙන්, එය මුළුමනින්ම ආත්මීය වන අතර ඔබට කිසිවක් ඔප්පු කළ නොහැක
ඔරියන් එඩ්වර්ඩ්ස්

74

යොමු කිරීම් දර්ශකයන්ට බෙහෙවින් සමාන ය, නමුත් ඒවා විශේෂයෙන් සකසා ඇත්තේ සම්පාදකයින් ප්‍රශස්තිකරණය කිරීම සඳහා උපකාරී වේ.

  • යොමු කිරීම් නිර්මාණය කර ඇත්තේ සම්පාදකයාට කුමන විචල්‍යයන් කුමන අන්වර්ථයන්ද යන්න සොයා ගැනීම සැලකිය යුතු ලෙස පහසු වන බැවිනි. ප්‍රධාන ලක්ෂණ දෙකක් ඉතා වැදගත් ය: “යොමු අංක ගණිතය” සහ නැවත යොමු කිරීම් නොමැත. සම්පාදක වේලාවේ විචල්‍යයන් වන අන්වර්ථයන් මොනවාදැයි සොයා ගැනීමට මේවා සම්පාදකයාට ඉඩ දෙයි.
  • මතක ලිපිනයන් නොමැති විචල්‍යයන් වෙත යොමු කිරීමට අවසර දෙනු ලැබේ, එනම් සම්පාදකයා ලේඛනයට ඇතුළත් කිරීමට තෝරා ගනී. ඔබ දේශීය විචල්‍යයක ලිපිනය ගන්නේ නම්, එය සම්පාදකයාට ලේඛනයක තැබීම ඉතා අපහසුය.

උදාහරණයක් ලෙස:

void maybeModify(int& x); // may modify x in some way

void hurtTheCompilersOptimizer(short size, int array[])
{
    // This function is designed to do something particularly troublesome
    // for optimizers. It will constantly call maybeModify on array[0] while
    // adding array[1] to array[2]..array[size-1]. There's no real reason to
    // do this, other than to demonstrate the power of references.
    for (int i = 2; i < (int)size; i++) {
        maybeModify(array[0]);
        array[i] += array[1];
    }
}

ප්‍රශස්තිකරණ සම්පාදකයෙකුට අප [0] සහ [1] තරමක් පොකුරකට ප්‍රවේශ වන බව වැටහෙනු ඇත. ඇල්ගොරිතම ප්‍රශස්තිකරණය කිරීමට එය කැමතියි:

void hurtTheCompilersOptimizer(short size, int array[])
{
    // Do the same thing as above, but instead of accessing array[1]
    // all the time, access it once and store the result in a register,
    // which is much faster to do arithmetic with.
    register int a0 = a[0];
    register int a1 = a[1]; // access a[1] once
    for (int i = 2; i < (int)size; i++) {
        maybeModify(a0); // Give maybeModify a reference to a register
        array[i] += a1;  // Use the saved register value over and over
    }
    a[0] = a0; // Store the modified a[0] back into the array
}

එවැනි ප්‍රශස්තිකරණයක් සිදු කිරීම සඳහා, ඇමතුම අතරතුර කිසිවක් [1] වෙනස් කළ නොහැකි බව ඔප්පු කළ යුතුය. මෙය කිරීමට පහසුය. මම කිසි විටෙකත් 2 ට වඩා අඩු නොවේ, එබැවින් අරාව [i] කිසි විටෙකත් අරාව [1] වෙත යොමු කළ නොහැක. සමහර විට මෝඩිෆයි () වෙත යොමු කිරීමක් ලෙස a0 ලබා දී ඇත (අන්වර්ථ අරා [0]). "යොමු" ගණිතයක් නොමැති නිසා, සම්පාදකයාට ඔප්පු කළ යුතුව ඇත්තේ සමහර විට මෝඩිෆයිට කිසි විටෙකත් x හි ලිපිනය නොලැබෙන අතර කිසිවක් අරාව වෙනස් නොකරන බව ඔප්පු කර ඇත [1].

අනාගත ඇමතුමකට [0] කියවීමට / ලිවීමට හැකියාවක් නොමැති බව ඔප්පු කළ යුතු අතර, එහි තාවකාලික ලේඛණ පිටපතක් අප සතුව ඇත. මෙය බොහෝ විට සනාථ කිරීම සුළුපටු ය, මන්ද බොහෝ අවස්ථාවන්හි දී සඳහන කිසි විටෙකත් පන්ති නිදසුනක් වැනි ස්ථිර ව්‍යුහයක ගබඩා නොවන බව පැහැදිලිය.

දැන් දර්ශකයන් සමඟ එකම දේ කරන්න

void maybeModify(int* x); // May modify x in some way

void hurtTheCompilersOptimizer(short size, int array[])
{
    // Same operation, only now with pointers, making the
    // optimization trickier.
    for (int i = 2; i < (int)size; i++) {
        maybeModify(&(array[0]));
        array[i] += array[1];
    }
}

හැසිරීම සමාන ය; සමහර විට මෝඩිෆයි කිසි විටෙකත් අරාව වෙනස් නොකරන බව ඔප්පු කිරීම දැන් වඩා දුෂ්කර ය [1], මන්ද අප දැනටමත් එයට දර්ශකයක් ලබා දී ඇත; බළලා බෑගයෙන් එළියට. දැන් එය වඩාත් දුෂ්කර සාධනය කළ යුතුව ඇත: සමහර විට මෝඩිෆයි හි ස්ථිතික විශ්ලේෂණයක් මඟින් එය කිසි විටෙකත් & x + 1 ට ලියන්නේ නැති බව සනාථ කරයි. තවද එය කිසි විටෙකත් අරාව [0] වෙත යොමු කළ හැකි දර්ශකයක් ඉතිරි නොකරන බව ඔප්පු කළ යුතුය. උපක්‍රමශීලී ලෙස.

නවීන සම්පාදකයින් ස්ථිතික විශ්ලේෂණයේ දී වඩා හොඳ සහ හොඳ වෙමින් පවතී, නමුත් ඔවුන්ට උදව් කිරීමට සහ යොමු කිරීම් භාවිතා කිරීම සැමවිටම සතුටක්.

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

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

F createF(int argument);

void extending()
{
    const F& ref = createF(5);
    std::cout << ref.getArgument() << std::endl;
};

සාමාන්‍යයෙන් තාවකාලික වස්තූන් වැනි ඇමතුම් මගින් නිර්මාණය කරන createF(5)ලද ප්‍රකාශනය අවසානයේ විනාශ වේ. කෙසේ වෙතත්, එම වස්තුව යොමු කිරීමකට බන්ධනය කිරීමෙන් ref, C ++ එම තාවකාලික වස්තුවෙහි ආයු කාලය refවිෂය පථයෙන් බැහැර වන තෙක් දීර් extend කරයි .


ශරීරය දෘශ්‍යමාන විය යුතු බව ඇත්ත. කෙසේ වෙතත්, පොයින්ටර් අංක ගණිත පොකුරක් සිදු නොවන බව ඔප්පු කිරීමට වඩා maybeModifyඒ හා සම්බන්ධ කිසිම දෙයක ලිපිනය නොසලකන බව තීරණය xකිරීම සැලකිය යුතු තරම් පහසුය.
Cort Ammon

මම විශ්වාස කරන්නේ ප්‍රශස්තිකාරකය දැනටමත් කර ඇත්තේ “පොයින්ටර් ගණිත පොකුරක් සිදු නොවන” බවයි.
බෙන් වොයිග්ට්

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

void maybeModify(int& x) { 1[&x]++; }ඉහත සඳහන් අනෙක් අදහස් සාකච්ඡා කරමින් සිටින අයෙකු යල්පැනගිය අදහස් දැක්වීමක් වැරදියට සලකුණු කළ බව මට හැඟේ
බෙන් වොයිග්ට්

69

ඇත්ත වශයෙන්ම, යොමු කිරීමක් ඇත්ත වශයෙන්ම දර්ශකයක් මෙන් නොවේ.

සම්පාදකයෙකු විචල්‍යයන්ට “යොමු” තබා, මතක ලිපිනයක් සමඟ නමක් සම්බන්ධ කරයි; සම්පාදනය කිරීමේදී ඕනෑම විචල්‍ය නාමයක් මතක ලිපිනයකට පරිවර්තනය කිරීම එහි කාර්යය වේ.

ඔබ යොමු කිරීමක් සාදන විට, ඔබ සම්පාදකයාට පවසන්නේ ඔබ දර්ශක විචල්‍යයට වෙනත් නමක් ලබා දෙන බවයි; විචල්‍යයක් විය නොහැකි අතර එසේ නොවිය හැකි නිසා යොමු කිරීම් “ශුන්‍යයට යොමු කළ නොහැක”.

දර්ශකයන් විචල්‍ය වේ; ඒවායේ වෙනත් විචල්‍යයක ලිපිනය අඩංගු වේ, නැතහොත් ශුන්‍ය විය හැකිය. වැදගත් දෙය නම්, දර්ශකයට වටිනාකමක් ඇති අතර, යොමු කිරීමකට ඇත්තේ එය යොමු කරන විචල්‍යයක් පමණි.

දැන් සැබෑ කේතය පිළිබඳ යම් පැහැදිලි කිරීමක්:

int a = 0;
int& b = a;

මෙන්න ඔබ පෙන්වා දෙන වෙනත් විචල්‍යයක් නිර්මාණය නොකරයි a; ඔබ අගය මතකයේ අන්තර්ගතයට තවත් නමක් එක් කරයි a. මෙම මතකය දැන් නම් දෙකක් ඇති aඅතර b, එය ඕනෑම නමකින් ආමන්ත්‍රණය කළ හැකිය.

void increment(int& n)
{
    n = n + 1;
}

int a;
increment(a);

ශ්‍රිතයක් අමතන විට, සම්පාදකයා සාමාන්‍යයෙන් තර්ක පිටපත් කිරීම සඳහා මතක අවකාශයන් ජනනය කරයි. ශ්‍රිත අත්සන මඟින් නිර්මාණය කළ යුතු අවකාශයන් නිර්වචනය කර මෙම අවකාශයන් සඳහා භාවිතා කළ යුතු නම ලබා දෙයි. පරාමිතියක් යොමු කිරීමක් ලෙස ප්‍රකාශ කිරීමෙන් සම්පාදකයාට ක්‍රම ඇමතුම අතරතුර නව මතක ඉඩක් වෙන් කිරීම වෙනුවට ආදාන විචල්‍ය මතක අවකාශය භාවිතා කරන ලෙස පවසයි. ඔබේ ශ්‍රිතය ඇමතුම් විෂය පථයේ ප්‍රකාශිත විචල්‍යයක් සෘජුවම හසුරුවනු ඇතැයි පැවසීම අමුතු දෙයක් ලෙස පෙනේ, නමුත් සංයුක්ත කේතය ක්‍රියාත්මක කිරීමේදී වැඩි විෂය පථයක් නොමැති බව මතක තබා ගන්න; සරල පැතලි මතකයක් පමණක් ඇති අතර ඔබේ ශ්‍රිත කේතයට ඕනෑම විචල්‍යයන් හැසිරවිය හැකිය.

බාහිර විචල්‍යයක් භාවිතා කරන විට මෙන් සම්පාදනය කිරීමේදී ඔබේ සම්පාදකයාට විමර්ශනය දැන ගැනීමට නොහැකි විය හැකි අවස්ථා දැන් තිබේ. එබැවින් යටි කේතයේ දර්ශකයක් ලෙස යොමු කිරීමක් ක්‍රියාත්මක කිරීමට හෝ නොවීමට ඉඩ ඇත. නමුත් මම ඔබට දුන් උදාහරණ වලදී, එය බොහෝ විට දර්ශකයක් සමඟ ක්‍රියාත්මක නොවනු ඇත.


2
යොමු කිරීමක් යනු විචල්‍යයකට නොව අනිවාර්යයෙන්ම l- අගය වෙත යොමු කිරීමකි. එම හේතුව නිසා, එය සැබෑ අන්වර්ථයකට වඩා (දර්ශක-කාල ඉදිකිරීම්) දර්ශකයකට වඩා සමීප ය. යොමු දැක්විය හැකි ප්‍රකාශන සඳහා උදාහරණ වන්නේ * p හෝ * p ++

5
හරි, මම පෙන්වා දුන්නේ යොමු කිරීමක් සැමවිටම නව විචල්‍යයක් තොගයේ නව තල්ලුවකට තල්ලු නොකරන ආකාරයට ය.
වින්සන්ට් රොබට්

1
In වින්සන්ට් රොබට්: එය දර්ශකයක් ලෙස ක්‍රියා කරයි ... ශ්‍රිතය පේළිගත කර ඇත්නම්, යොමු සහ දර්ශකය යන දෙකම ප්‍රශස්ත වනු ඇත. ශ්‍රිත ඇමතුමක් තිබේ නම්, වස්තුවේ ලිපිනය ශ්‍රිතයට යැවිය යුතුය.
බෙන් වොයිග්ට්

1
int * p = NULL; int & r = * p; NULL වෙත යොමු කිරීම; if (r) {} -> boOm;)
sree

2
සංයුක්ත වේදිකාව කෙරෙහි මෙම අවධානය යොමු වී ඇති බව පෙනේ, ක්‍රියාත්මක වන වේලාවට යොමු යොමු කළ හැකි බව ඔබට මතක ඇති තෙක්, ස්ථිතික අන්වර්ථකරණය කවුළුවෙන් පිටතට යයි. (ඉන්පසු යොමු කිරීම් සාමාන්‍යයෙන් දර්ශකයන් ලෙස ක්‍රියාත්මක වේ, නමුත් ප්‍රමිතියට මෙම ක්‍රමය අවශ්‍ය නොවේ.)
underscore_d

45

යොමු කිරීමක් කිසි විටෙකත් විය නොහැකිය NULL.


10
ප්‍රති-උදාහරණයක් සඳහා මාර්ක් රැන්සම්ගේ පිළිතුර බලන්න. යොමු කිරීම් පිළිබඳ බොහෝ විට තහවුරු කරන ලද මිථ්‍යාව මෙය වන නමුත් එය මිථ්‍යාවකි. ප්‍රමිතියෙන් ඔබට ඇති එකම සහතිකය නම්, ඔබට NULL යොමු කිරීමක් ඇති විට වහාම UB ඇති බවයි. නමුත් එය සමාන වන්නේ "මෙම මෝටර් රථය ආරක්ෂිතයි, එයට කිසි විටෙකත් මාර්ගයෙන් බැස යා නොහැක. (ඔබ එය කෙසේ හෝ පාරෙන් ඉවතට ගෙන ගියහොත් සිදුවිය හැකි දේ සම්බන්ධයෙන් අපි කිසිදු වගකීමක්
නොදරන්නෙමු

17
macmaster: වලංගු වැඩසටහනක , යොමු කිරීමක් අහෝසි කළ නොහැක. නමුත් දර්ශකයකට හැකිය. මෙය මිථ්‍යාවක් නොවේ, මෙය සත්‍යයකි.
user541686

8
E මෙහර්දාඩ් ඔව්, වලංගු වැඩසටහන් පාරේ රැඳේ. නමුත් ඔබේ වැඩසටහන සත්‍ය වශයෙන්ම ක්‍රියාත්මක කිරීමට කිසිදු මාර්ග බාධකයක් නොමැත. මාර්ගයේ විශාල කොටස්වල ඇත්ත වශයෙන්ම සලකුණු නොමැත. එබැවින් රාත්‍රියේ පාරෙන් බැසීම අතිශයින්ම පහසුය. මෙය සිදුවිය හැකි බව ඔබ දන්නා එවැනි දෝෂ නිදොස් කිරීම සඳහා ඉතා වැදගත් වේ : ශුන්‍ය යොමු කිරීම මඟින් ඔබේ වැඩසටහන බිඳ වැටීමට පෙර එය ප්‍රචාරය කළ හැකිය. එය ඇති විට ඔබට void Foo::bar() { virtual_baz(); }එම සෙග්ෆෝල්ට් වැනි කේත ඇත. යොමු කිරීම් අහෝසි විය හැකි බව ඔබ නොදන්නේ නම්, ඔබට ශුන්‍යය එහි මූලාරම්භය දක්වා සොයාගත නොහැක.
cmaster -

4
int * p = NULL; int & r = * p; NULL වෙත යොමු කිරීම; if (r) {} -> boOm;) -
sree

10
reeSree int &r=*p;යනු නිර්වචනය නොකළ හැසිරීමකි. එම අවස්ථාවේදී, ඔබට “NULL වෙත යොමු කරන යොමු කිරීමක්” නොමැත, ඔබට කිසිසේත් තර්කානුකූල කළ නොහැකි
cdhowie

35

වෙනත් අගයකට වක්‍රව ප්‍රවේශ වීම සඳහා යොමු සහ දර්ශක යන දෙකම භාවිතා කරන අතර, යොමු සහ දර්ශක අතර වැදගත් වෙනස්කම් දෙකක් තිබේ. පළමුවැන්න නම්, යොමු කිරීමක් සෑම විටම වස්තුවකට යොමු වීමයි: එය ආරම්භයක් නොමැතිව යොමු කිරීමක් අර්ථ දැක්වීම දෝෂයකි. පැවරුමේ හැසිරීම දෙවන වැදගත් වෙනස වේ: යොමු කිරීමකට පැවරීම යොමු කිරීම බැඳී ඇති වස්තුව වෙනස් කරයි; එය වෙනත් වස්තුවක් වෙත යොමු කිරීම ප්‍රතික්ෂේප නොකරයි. ආරම්භ කිරීමෙන් පසු, යොමු කිරීමක් සෑම විටම එකම යටින් පවතින වස්තුවට යොමු වේ.

මෙම වැඩසටහන් කොටස් දෙක සලකා බලන්න. පළමුවෙන්ම, අපි එක් දර්ශකයක් තවත් දර්ශකයකට පවරමු:

int ival = 1024, ival2 = 2048;
int *pi = &ival, *pi2 = &ival2;
pi = pi2;    // pi now points to ival2

පැවරුමෙන් පසුව, ival, pi විසින් ආමන්ත්‍රණය කරන ලද වස්තුව නොවෙනස්ව පවතී. පැවරුම pi හි අගය වෙනස් කරයි, එය වෙනත් වස්තුවකට යොමු කරයි. දැන් යොමු දෙකක් පවරන සමාන වැඩසටහනක් සලකා බලන්න:

int &ri = ival, &ri2 = ival2;
ri = ri2;    // assigns ival2 to ival

මෙම පැවරුම ival වෙනස් කරයි, රී විසින් යොමු කරන ලද අගය මිස යොමු කිරීමම නොවේ. පැවරුමෙන් පසුව, යොමු දෙක තවමත් ඒවායේ මුල් වස්තූන් වෙත යොමු වන අතර, එම වස්තූන්ගේ වටිනාකම දැන් සමාන වේ.


“යොමු කිරීමක් සෑම විටම වස්තුවකට යොමු කරයි” යනු සම්පූර්ණයෙන්ම අසත්‍යයකි
බෙන් වොයිගට්

32

වියුක්ත හෝ ශාස්ත්‍රීය ආකාරයකින් පරිගණක භාෂා හැදෑරීමට ඔබ හුරු නැතිනම් අර්ථාන්විත වෙනසක් ඇත.

ඉහළම මට්ටමේ දී, යොමු දැක්වීමේ අදහස නම් ඒවා විනිවිද පෙනෙන "අන්වර්ථයන්" ය. ඔබේ පරිගණකය ඒවා ක්‍රියාත්මක කිරීම සඳහා ලිපිනයක් භාවිතා කළ හැකි නමුත් ඔබ ඒ ගැන කරදර විය යුතු නැත: ඔබ ඒවා පවතින වස්තුවක් සඳහා “තවත් නමක්” ලෙස සිතිය යුතු අතර සින්ටැක්ස් එය පිළිබිඹු කරයි. ඒවා දර්ශකයන්ට වඩා දැඩි බැවින් ඔබ කම්පනකාරී යොමු කිරීමක් සෑදීමට සූදානම් වන විට ඔබේ කම්පයිලරයට වඩාත් විශ්වාසදායක ලෙස අනතුරු ඇඟවිය හැකිය.

ඉන් ඔබ්බට, ඇත්ත වශයෙන්ම දර්ශකයන් සහ යොමු කිරීම් අතර යම් ප්‍රායෝගික වෙනස්කම් තිබේ. ඒවා භාවිතා කිරීම සඳහා වන වාක්‍ය ඛණ්ඩය පැහැදිලිවම වෙනස් වන අතර, ඔබට “නැවත ආසන” යොමු කළ නොහැක, කිසිවක් ගැන සඳහනක් නැත, හෝ යොමු කිරීම් සඳහා යොමු කිරීම් තිබිය නොහැක.


27

යොමු කිරීම වෙනත් විචල්‍යයක් සඳහා අන්වර්ථයක් වන අතර දර්ශකය විචල්‍යයක මතක ලිපිනය දරයි. සම්මතයන් සාමාන්‍යයෙන් ශ්‍රිත පරාමිතීන් ලෙස භාවිතා කරයි, එවිට සම්මත වස්තුව පිටපත නොව වස්තුවම වේ.

    void fun(int &a, int &b); // A common usage of references.
    int a = 0;
    int &b = a; // b is an alias for a. Not so common to use. 

20

ඔබට ගතවන ඕනෑම අවකාශයක කිසිදු අතුරු ආබාධයක් (කේත ක්‍රියාත්මක නොකර) ඔබට සැබවින්ම දැකිය නොහැකි බැවින් එය කොපමණ ඉඩ ප්‍රමාණයක් ගත යුතුද යන්න ගැටළුවක් නොවේ.

අනෙක් අතට, යොමු කිරීම් සහ දර්ශකයන් අතර ඇති එක් ප්‍රධාන වෙනසක් නම්, නියත යොමු කිරීම් විෂය පථයෙන් බැහැර වන තුරු, නියත යොමු කිරීම් සඳහා පවරා ඇති තාවකාලිකයන් සජීවීව පැවතීමයි.

උදාහරණයක් වශයෙන්:

class scope_test
{
public:
    ~scope_test() { printf("scope_test done!\n"); }
};

...

{
    const scope_test &test= scope_test();
    printf("in scope\n");
}

මුද්‍රණය කරනු ඇත:

in scope
scope_test done!

ScopeGuard වැඩ කිරීමට ඉඩ දෙන භාෂා යාන්ත්‍රණය මෙයයි.


1
ඔබට යොමු කිරීමක ලිපිනය ගත නොහැක, නමුත් එයින් අදහස් කරන්නේ ඔවුන් භෞතිකව ඉඩ ලබා නොගන්නා බවයි. ප්‍රශස්තිකරණය හැර, ඔවුන්ට නිසැකවම හැකි ය.
කක්ෂයේ සැහැල්ලු රේස්

2
බලපෑම තිබියදීත්, "තොගයේ සඳහනක් කිසිසේත් ඉඩක් නොගනී" යන්න අසත්‍යයකි.
කක්ෂයේ සැහැල්ලු ධාවන

1
Oma ටොමලක්, එය සම්පාදකයා මත ද රඳා පවතී. නමුත් ඔව්, එය පැවසීම ටිකක් අවුල් සහගතය. එය ඉවත් කිරීම අවුල් සහගත වනු ඇතැයි මම සිතමි.
MSN

1
කිසියම් විශේෂිත අවස්ථාවකදී එය එසේ නොවිය හැකිය. එබැවින් නිශ්චිත ප්‍රකාශයක් වැරදියි. ඒකයි මම කියන්නේ. :) [ගැටලුව සම්බන්ධයෙන් ප්‍රමිතිය පවසන දේ මට මතක නැත; විමර්ශන සාමාජිකයින්ගේ නීති රීති වලට “යොමු කිරීම් සඳහා ඉඩ ප්‍රමාණයක් ගත හැකිය” යන සාමාන්‍ය රීතියක් ලබා දිය හැකිය, නමුත් මගේ ප්‍රමිතියේ පිටපතක් මා සමඟ මෙහි වෙරළ තීරයේ නොමැත: D]
කක්ෂයේ සැහැල්ලු ධාවන තරඟ

20

මෙය නිබන්ධනය මත පදනම් වේ . ලියා ඇති දෙයින් එය වඩාත් පැහැදිලි වේ:

>>> The address that locates a variable within memory is
    what we call a reference to that variable. (5th paragraph at page 63)

>>> The variable that stores the reference to another
    variable is what we call a pointer. (3rd paragraph at page 64)

එය මතක තබා ගැනීම සඳහා,

>>> reference stands for memory location
>>> pointer is a reference container (Maybe because we will use it for
several times, it is better to remember that reference.)

එපමණක්ද නොව, අපට ඕනෑම දර්ශක නිබන්ධනයකට යොමු විය හැකි පරිදි, දර්ශකය යනු දර්ශක අංක ගණිතයෙන් සහය දක්වන වස්තුවක් වන අතර එමඟින් දර්ශකය අරාවකට සමාන වේ.

පහත දැක්වෙන ප්‍රකාශය දෙස බලන්න,

int Tom(0);
int & alias_Tom = Tom;

alias_Tomලෙස තේරුම් ගත හැකි alias of a variable(සමග විවිධ typedefවන, alias of a type) Tom. එවැනි ප්‍රකාශයක පාරිභාෂිතය අමතක කිරීම ද සුදුසු ය Tom.


1
පංතියකට විමර්ශන විචල්‍යයක් තිබේ නම්, එය ආරම්භක ලැයිස්තුවේ ශුන්‍ය හෝ වලංගු වස්තුවක් සමඟ ආරම්භ කළ යුතුය.
වැරදි විප්ලවය

1
මෙම පිළිතුරේ ඇති වචන එය බොහෝ ප්‍රයෝජනවත් නොවන තරමට ව්‍යාකූල වේ. එසේම, is විග්‍රහය, ඔබ සමඟ යොමු කිරීමක් ආරම්භ කිරීමට පා readers කයන්ට බැරෑරුම් ලෙස නිර්දේශ nullptrකරනවාද? ඔබ ඇත්තටම මෙම ත්‍රෙඩ් එකේ වෙනත් කොටසක් කියවා තිබේද, නැත්නම් ...?
underscore_d

1
මගේ නරක, මම කියපු මෝඩ දේට සමාවෙන්න. ඒ කාලය වන විට මට නින්ද අහිමි වී තිබිය යුතුය. 'nullptr සමඟ ආරම්භ කිරීම' සම්පූර්ණයෙන්ම වැරදිය.
වැරදි විප්ලවය

19

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

int& j = i;

එය අභ්‍යන්තරව බවට පත්වේ

int* const j = &i;

13
C ++ ප්‍රමිතිය මෙය නොවේ, ඔබේ පිළිතුර විස්තර කර ඇති ආකාරයට සම්පාදකයාට යොමු කිරීම් ක්‍රියාත්මක කිරීම අවශ්‍ය නොවේ.
jogojapan

og ජෝජෝජපන්: සී ++ සම්පාදකයෙකුට යොමු කිරීමක් ක්‍රියාත්මක කිරීම සඳහා වලංගු වන ඕනෑම ක්‍රමයක් එය constදර්ශකයක් ක්‍රියාත්මක කිරීම සඳහා වලංගු ක්‍රමයකි . යොමු කිරීමක් සහ දර්ශකයක් අතර වෙනසක් ඇති බව එම නම්‍යශීලී බව ඔප්පු නොකරයි.
බෙන් වොයිගට්

2
EnBenVoigt එකක් වලංගු එකක් ක්‍රියාත්මක කිරීම අනෙකා වලංගු ක්‍රියාත්මක කිරීමක් බව සත්‍යයක් විය හැකි නමුත් එය මෙම සංකල්ප දෙකේ අර්ථ දැක්වීම් වලින් පැහැදිලි ආකාරයකින් අනුගමනය නොකරයි. හොඳ පිළිතුරක් අර්ථ දැක්වීම් වලින් ආරම්භ විය හැකි අතර, අවසානයේදී දෙදෙනා එක හා සමාන වීම පිළිබඳ ප්‍රකාශය සත්‍ය වන්නේ මන්ද යන්න නිරූපණය කරයි. මෙම පිළිතුර වෙනත් පිළිතුරු සඳහා යම් ආකාරයක අදහස් දැක්වීමක් ලෙස පෙනේ.
ජෝගෝජපන්

යොමු කිරීම යනු වස්තුවකට ලබා දෙන තවත් නමකි. ඔබට වෙනස පැවසිය නොහැකි තාක් කල්, සම්පාදකයාට ඕනෑම ආකාරයක ක්‍රියාත්මක කිරීමට අවසර ඇත, මෙය “as-if” රීතිය ලෙස හැඳින්වේ. මෙහි ඇති වැදගත් කොටස නම් ඔබට වෙනස පැවසිය නොහැක. දර්ශකයක ආචයනයක් නොමැති බව ඔබට සොයාගත හැකි නම්, සම්පාදකයා දෝෂ සහිතය. යොමුවකට ගබඩාවක් නොමැති බව ඔබට සොයාගත හැකි නම්, සම්පාදකයා තවමත් අනුකූල වේ.
sp2danny

18

සෘජු පිළිතුර

C ++ හි යොමු කිරීමක් යනු කුමක්ද? වස්තු වර්ගයක් නොවන වර්ගයේ නිශ්චිත අවස්ථාවක් .

C ++ හි දර්ශකය යනු කුමක්ද? වස්තු වර්ගයක් වන වර්ගයේ නිශ්චිත අවස්ථාවක් .

සිට වස්තුව වර්ගය ගත් ISO C ++ අර්ථ දැක්වීම :

වස්තුව වර්ගය අ (සමහරවිට වේ cv උත්සවයකට වර්ගය, සැඳහුම වර්ගය නොවේ නොවන බව -qualified) වර්ගය, හා නොවේ cv අඩුව.

දැන ගැනීම වැදගත් විය හැකිය, වස්තු වර්ගය යනු C ++ හි විශ්වයේ වර්ගයේ ඉහළ මට්ටමේ කාණ්ඩයකි. යොමු කිරීම ද ඉහළ මට්ටමේ කාණ්ඩයකි. නමුත් දර්ශකය එසේ නොවේ.

සංයෝග වර්ගයේ සන්දර්භය තුළ දර්ශකයන් සහ යොමු කිරීම් එකට සඳහන් වේ. මෙයට මූලික වශයෙන් හේතු වී ඇත්තේ (සහ දීර් extended කරන ලද) සී වෙතින් උරුම වූ ප්‍රකාශක සින්ටැක්ස් වල ස්වභාවයයි. (මීට අමතරව, එහි C ++ 11 සිට යොමු declarator එකකට වඩා වැඩි වගේ, සූචක තවමත් "unityped" වන අතර ඇත: &+ &&එදිරිව *.) මෙම සන්දර්භය තුළ සී සමාන ශෛලිය සමග "දීර්ඝ" විසින් භාෂාවක් විශේෂිත කෙටුම්පත් තරමක් සාධාරණ වන්නේ ඒ නිසා . (මම තවමත් declarators අපද්රව්ය කාරක රීති ද සින්ටැක්ටික් expressiveness තර්ක ගොඩක් , මානව හා පරිශීලකයන් නිර්මාණයන් දෙකම දුෂ්කර කරයි. මේ අනුව, ඔවුන් සියලු කිරීමට සුදුසුකම් නැති බිල්ට්නව භාෂා සැලසුමකින්. මෙය PL නිර්මාණය පිළිබඳ සම්පූර්ණයෙන්ම වෙනස් මාතෘකාවකි.)

එසේ නොමැති නම්, එක් එක් යොමු කිරීම් සහිත නිශ්චිත වර්ගයක් ලෙස දර්ශකයන් සුදුසුකම් ලැබිය හැකි වීම වැදගත් නොවේ. ඒවා හුදෙක් සින්ටැක්ස් සමානතාවයට අමතරව පොදු ගුණාංග ඉතා ස්වල්පයක් බෙදා ගනී, එබැවින් බොහෝ අවස්ථාවන්හිදී ඒවා එකට දැමීමේ අවශ්‍යතාවයක් නොමැත.

ඉහත ප්‍රකාශ වල සඳහන් වන්නේ “දර්ශකයන්” සහ “යොමු කිරීම්” වර්ග ලෙස පමණි. ඒවායේ අවස්ථා (විචල්යයන් වැනි) ගැන උනන්දුවක් දක්වන ප්රශ්න කිහිපයක් තිබේ. බොහෝ වැරදි වැටහීම් ද ඇත.

ඉහළ මට්ටමේ කාණ්ඩවල වෙනස්කම් මගින් සෘජුවම දර්ශකයන් සමඟ බැඳී නොමැති බොහෝ කොන්ක්‍රීට් වෙනස්කම් දැනටමත් හෙළි කළ හැකිය:

  • වස්තු වර්ග වලට ඉහළ මට්ටමේ cvසුදුසුකම් තිබිය හැකිය. යොමු කිරීම් කළ නොහැක.
  • වියුක්ත යන්ත්‍ර අර්ථ නිරූපණයට අනුව වස්තු වර්ගවල විචල්‍යතාව ගබඩා කරයි . ආචයනය ගබඩා කිරීම සඳහා අවශ්‍ය නොවේ (විස්තර සඳහා පහත වැරදි වැටහීම් පිළිබඳ කොටස බලන්න).
  • ...

යොමු කිරීම් පිළිබඳ තවත් විශේෂ නීති කිහිපයක්:

  • සංයුක්ත ප්‍රකාශකයන් යොමු කිරීම් වලට වඩා සීමා කර ඇත.
  • යොමු කිරීම් බිඳ වැටිය හැකිය .
    • &&පරාමිති පිළිබඳ විශේෂ රීති ("ඉදිරියට යැවීමේ යොමු කිරීම්" ලෙස) අච්චු පරාමිති අඩුකිරීමේදී බිඳ වැටීම මත පදනම්ව පරාමිතීන් "පරිපූර්ණ ඉදිරියට යැවීමට " ඉඩ දෙයි .
  • ආරම්භයේදී යොමු කිරීම් වලට විශේෂ නීති ඇත. යොමු වර්ගයක් ලෙස ප්‍රකාශයට පත් කරන ලද විචල්‍යයේ ආයු කාලය දීර්. කිරීම හරහා සාමාන්‍ය වස්තූන්ට වෙනස් විය හැකිය.
    • BTW, ආරම්භකත්වය වැනි තවත් සන්දර්භ කිහිපයක්, std::initializer_listජීවිත කාලය දීර් extension කිරීමේ සමාන නීති කිහිපයක් අනුගමනය කරයි. එය තවත් පණුවන් කෑන් ය.
  • ...

වැරදි වැටහීම්

සින්ටැක්ටික් සීනි

යොමුව සින්ටැක්ටික් සීනි බව මම දනිමි, එබැවින් කේතය කියවීමට හා ලිවීමට පහසුය.

තාක්ෂණික වශයෙන්, මෙය සරල වැරදිය. යොමු කිරීම් C ++ හි ඇති වෙනත් කිසිදු අංගයක සින්ටැක්ටික් සීනි නොවේ, මන්දයත් ඒවා කිසිදු අර්ථකථන වෙනසක් නොමැතිව වෙනත් අංග මගින් හරියටම ප්‍රතිස්ථාපනය කළ නොහැකි බැවිනි.

(එලෙසින්ම, ලැම්ඩා-ප්රකාශනය වහන්සේගේ නොවන C ++ වෙනත් ඕනෑම ලක්ෂණ සින්ටැක්ටික් සීනි එය හරියටම සමාන "නම් නොකල" ගුණ ඇති යන්තරයෙනි නොහැකි නිසා අල්ලා ගනු විචල්ය ප්රකාශයට පත් පිණිස වැනි විචල්යතා ආරම්භය සඳහා විය හැකි බැවින්, වැදගත් විය හැකි, සැලකිය යුතු.)

C ++ සතුව ඇත්තේ මෙම දැඩි අර්ථයෙන් සින්ටැක්ටික් සීනි වර්ග කිහිපයක් පමණි. එක් උදාහරණයක් (C උරුම) එම බිල්ට් (-වුවමනාවන් නොවන) ක්රියාකරු වේ []කරන, හරියටම බිල්ට් ක්රියාකරු ඒකජ කට එකතුවක් විශේෂිත ආකාරයේ එකම අර්ථ විචාර ලක්ෂණ සහිත අර්ථ *හා ද්විමය+ .

ගබඞා

ඉතින්, දර්ශකයක් සහ යොමු කිරීමක් යන දෙකම එකම මතක ප්‍රමාණයක් භාවිතා කරයි.

ඉහත ප්‍රකාශය වැරදිය. එවැනි වැරදි වැටහීම් වලක්වා ගැනීම සඳහා, ඒ වෙනුවට ISO C ++ නීති දෙස බලන්න:

සිට [intro.object] / 1 :

... වස්තුවක් එහි ඉදිකිරීම් කාලය තුළ, එහි ජීවිත කාලය පුරාම සහ විනාශයේ කාල පරිච්ඡේදයේදී ගබඩා කලාපයක් අල්ලා ගනී. ...

සිට [dcl.ref] / 4 :

යොමු කිරීමකට ගබඩා කිරීම අවශ්‍යද නැද්ද යන්න නිශ්චිතව දක්වා නැත.

මේවා අර්ථකථන ගුණාංග බව සලකන්න .

ප්‍රායෝගික විද්‍යාව

භාෂා සැලසුමේ අර්ථයෙන් යොමු දැක්වීම් සමඟ සම්බන්ධ කිරීමට තරම් සුදුසුකම් නොමැති වුවද, වෙනත් සන්දර්භයන් තුළ ඒවා අතර තේරීමක් කිරීම විවාදයට තුඩු දෙන තර්ක කිහිපයක් තවමත් පවතී, උදාහරණයක් ලෙස, පරාමිති වර්ග මත තේරීම් කරන විට.

නමුත් මෙය සම්පූර්ණ කතාව නොවේ. මම අදහස් කළේ, ඔබ සලකා බැලිය යුතු කරුණු හා යොමු කිරීම් වලට වඩා බොහෝ දේ ඇත.

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

  • සමහර විට භාෂා නීති සඳහා නිශ්චිත වර්ග භාවිතා කිරීම අවශ්‍ය වේ. ඔබට මෙම අංග භාවිතා කිරීමට අවශ්‍ය නම්, නීතිවලට අවනත වන්න.
    • පිටපත් සාදන්නන්ට& 1 වන පරාමිති වර්ගය ලෙස විශේෂිත cv - යොමු වර්ගය අවශ්‍ය වේ . (සාමාන්‍යයෙන් එය constසුදුසුකම් ලැබිය යුතුය .)
    • 1 වන පරාමිති වර්ගය ලෙස චලනය වන ඉදිකිරීම්කරුවන්ට නිශ්චිත වර්ගයේ සීවී - &&යොමු වර්ගය අවශ්‍ය වේ . (සාමාන්‍යයෙන් සුදුසුකම් ලැබිය යුතු අය නොසිටිය යුතුය.)
    • ක්‍රියාකරුවන්ගේ නිශ්චිත බර පැටවීම සඳහා යොමු හෝ යොමු නොවන වර්ග අවශ්‍ය වේ. උදාහරණයක් වශයෙන්:
      • operator=විශේෂ සාමාජික කාර්යයන් ලෙස අධික ලෙස පැටවීම සඳහා පිටපත් / චලන ඉදිකිරීම්කරුවන්ගේ 1 වන පරාමිතියට සමාන යොමු වර්ග අවශ්‍ය වේ.
      • පෝස්ට්ෆික්ස් ++සඳහා ව්‍යාජ අවශ්‍ය වේ int.
      • ...
  • පාස්-බයි-අගය (එනම් යොමු නොවන වර්ග භාවිතා කිරීම) ප්‍රමාණවත් බව ඔබ දන්නේ නම්, එය කෙලින්ම භාවිතා කරන්න, විශේෂයෙන් සී ++ 17 අනිවාර්ය පිටපත් ඉවත් කිරීමට සහාය වන ක්‍රියාත්මක කිරීමක් භාවිතා කරන විට. ( අවවාදයයි : කෙසේ වෙතත්, කිරීමට , දීර්ඝ වශයෙන් අවශ්යතාව ගැන හේතුව කළ හැකි ඉතා සංකීර්ණ .)
  • ඔබ අයිතිය සමග සමහර හැන්ඩ්ල් ක්රියාත්මක කිරීමට අවශ්ය නම්, වැනි ස්මාර්ට් සූචක භාවිතා unique_ptrසහ shared_ptr(හෝ වර්ණ සම්පන්නා විය අය සමඟ පවා ඔබ විසින් ඔබ විය ඔවුන් අවශ්ය නම් විනිවිද නොපෙනෙන ), ඒ වෙනුවට අමු සූචක වඩා.
  • ඔබ යම් පරාසයක් හරහා යම් පුනරාවර්තන සිදු කරන්නේ නම්, අමු දර්ශකයන් වෙනුවට අමු දර්ශක භාවිතා කරන්න (හෝ සම්මත පුස්තකාලය විසින් තවමත් ලබා දී නොමැති සමහර පරාසයන්) භාවිතා කරන්න, අමු පොයින්ටර්ස් වඩාත් නිශ්චිතව (උදා: අඩු ශීර්ෂ පරායත්තයන් සඳහා) වඩාත් හොඳින් කරනු ඇතැයි ඔබට ඒත්තු ගැන්වී තිබේ නම් නඩු.
  • පසු-අගය ප්‍රමාණවත් බව ඔබ දන්නේ නම් සහ ඔබට පැහැදිලි අර්ථකථන කිහිපයක් අවශ්‍ය නම් std::optional, අමු දර්ශකයන්ට වඩා එතීම භාවිතා කරන්න .
  • ඉහත හේතු සඳහා පාස්-බයි-අගය සුදුසු නොවන බව ඔබ දන්නේ නම්, සහ ඔබට අර්ථ නිරූපණයන් අවශ්‍ය නොවන්නේ නම්, {lvalue, rvalue, forwarding} -references භාවිතා කරන්න.
  • සාම්ප්‍රදායික දර්ශකය වැනි අර්ථ නිරූපණයන් ඔබට අවශ්‍ය වූ විට පවා, observer_ptrපුස්තකාල මූලික ටීඑස් වැනි බොහෝ විට වඩාත් සුදුසු යමක් තිබේ.

එකම ව්‍යතිරේකය වත්මන් භාෂාවෙන් ක්‍රියාත්මක කළ නොහැක:

  • ඔබ ඉහත ස්මාර්ට් පොයින්ටර් ක්‍රියාත්මක කරන විට, ඔබට අමු දර්ශකයන් සමඟ කටයුතු කිරීමට සිදුවනු ඇත.
  • විශේෂිත භාෂා-අන්තර්ක්‍රියාකාරී ක්‍රියාකාරකම් සඳහා වැනි කරුණු අවශ්‍ය වේ operator new. (කෙසේ වෙතත්, cv - void*තවමත් බෙහෙවින් වෙනස් සහ ආරක්ෂිත සාමාන්ය වස්තුව සූචක සාපේක්ෂව ඔබ නොවන සමහර අනුකූල දීර්ඝ මත රඳා ඇති නම් හැරෙන්නට එය අනපේක්ෂිත පහිටුම් දක්වනය arithmetics සිදු පාලනය නිසා ය void*GNU ගේ වගේ.)
  • ක්‍රියාකාරී දර්ශකයන් ග්‍රහණයෙන් තොරව ලැම්බඩා ප්‍රකාශන වලින් පරිවර්තනය කළ හැකි අතර ක්‍රියාකාරී යොමු කිරීම් කළ නොහැක. එවැනි අවස්ථාවන් සඳහා සාමාන්‍ය නොවන කේතයන්හි ක්‍රියාකාරී දර්ශක භාවිතා කිරීමට ඔබට සිදුවේ, ඔබට හිතාමතාම අහෝසි කළ හැකි අගයන් අවශ්‍ය නොවේ.

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

  • ඔබ පැරණි විලාසිතාවේ (සී) ඒපීඅයි වෙත සේවය කළ යුතුය.
  • විශේෂිත C ++ ක්‍රියාත්මක කිරීමේ ABI අවශ්‍යතා සපුරාලිය යුතුය.
  • නිශ්චිත ක්‍රියාත්මක කිරීම්වල උපකල්පන මත පදනම්ව ඔබට විවිධ භාෂා ක්‍රියාත්මක කිරීම් (විවිධ එකලස් කිරීම්, භාෂා ධාවන කාලය සහ සමහර ඉහළ මට්ටමේ සේවාදායක භාෂාවන්ගේ එෆ්එෆ්අයි ඇතුළුව) සමඟ ක්‍රියාත්මක විය යුතුය.
  • සමහර ආන්තික අවස්ථාවන්හිදී ඔබ පරිවර්තනයේ කාර්යක්ෂමතාව (සම්පාදනය සහ සම්බන්ධ කිරීම) වැඩි දියුණු කළ යුතුය.
  • සමහර ආන්තික අවස්ථාවන්හිදී ඔබට සංකේත පිපිරීමෙන් වැළකී සිටිය යුතුය.

භාෂා මධ්‍යස්ථභාවය අවවාද කරයි

ඔබ සමහර ගූගල් සෙවුම් ප්‍රති result ල හරහා ප්‍රශ්නය බැලීමට පැමිණියහොත් (C ++ සඳහා විශේෂිත නොවේ) , මෙය වැරදි ස්ථානයක් වීමට බොහෝ දුරට ඉඩ ඇත.

සී ++ හි යොමු කිරීම් තරමක් "අමුතු" ය, එය මූලික වශයෙන් පළමු පන්තිය නොවන බැවින්: ඒවා වස්තූන් හෝ යොමු කරනු ලබන කාර්යයන් ලෙස සලකනු ලැබේ, එබැවින් ඔවුන්ට පළමු පන්තියේ මෙහෙයුම් සඳහා සහාය වීමට අවස්ථාවක් නොලැබේ . සාමාජික ප්‍රවේශ ක්‍රියාකරු යොමු කරන ලද වස්තුවට ස්වාධීනව. වෙනත් භාෂාවන්ට ඔවුන්ගේ යොමු කිරීම් වලට සමාන සීමාවන් තිබිය හැකිය හෝ නොතිබිය හැකිය.

C ++ හි යොමු කිරීම් විවිධ භාෂාවන් හරහා අර්ථය ආරක්ෂා නොකරනු ඇත. නිදසුනක් ලෙස, පොදුවේ යොමු කිරීම් C ++ වැනි අගයන් මත අද්විතීය ගුණාංග අදහස් නොකෙරේ, එබැවින් එවැනි උපකල්පන වෙනත් භාෂාවලින් ක්‍රියා නොකරනු ඇත (තවද ඔබට ප්‍රති-නියැදි ඉතා පහසුවෙන් සොයාගත හැකිය, උදා: ජාවා, සී #, ...).

පොදුවේ විවිධ ක්‍රමලේඛන භාෂාවල යොමු කිරීම් අතර පොදු ගුණාංග කිහිපයක් තවමත් පැවතිය හැකිය, නමුත් SO හි වෙනත් ප්‍රශ්න සඳහා එය තබමු.

(පැති සටහනක්: ALGOL 68 එදිරිව පීඑල් / අයි වැනි ඕනෑම "සී-වැනි" භාෂාවන් සම්බන්ධ වීමට පෙර ප්‍රශ්නය වැදගත් විය හැකිය .)


17

C ++ හි දර්ශකයක් වෙත යොමු කිරීමක් කළ හැකි නමුත් ආපසු හැරවීම කළ නොහැකි ය යන්නෙන් අදහස් කරන්නේ යොමු කිරීමකට දර්ශකයක් කළ නොහැකි බවයි. දර්ශකය වෙත යොමු කිරීම මඟින් දර්ශකය වෙනස් කිරීම සඳහා පිරිසිදු වාක්‍ය ඛණ්ඩයක් සපයයි. මෙම උදාහරණය දෙස බලන්න:

#include<iostream>
using namespace std;

void swap(char * &str1, char * &str2)
{
  char *temp = str1;
  str1 = str2;
  str2 = temp;
}

int main()
{
  char *str1 = "Hi";
  char *str2 = "Hello";
  swap(str1, str2);
  cout<<"str1 is "<<str1<<endl;
  cout<<"str2 is "<<str2<<endl;
  return 0;
}

ඉහත වැඩසටහනේ සී අනුවාදය සලකා බලන්න. C හි දී ඔබට දර්ශකයට දර්ශකය භාවිතා කිරීමට සිදුවේ (බහු අවිනිශ්චිතතාව), එය ව්‍යාකූලත්වයට තුඩු දෙන අතර වැඩසටහන සංකීර්ණ ලෙස පෙනේ.

#include<stdio.h>
/* Swaps strings by swapping pointers */
void swap1(char **str1_ptr, char **str2_ptr)
{
  char *temp = *str1_ptr;
  *str1_ptr = *str2_ptr;
  *str2_ptr = temp;
}

int main()
{
  char *str1 = "Hi";
  char *str2 = "Hello";
  swap1(&str1, &str2);
  printf("str1 is %s, str2 is %s", str1, str2);
  return 0;
}

දර්ශකය වෙත යොමු කිරීම පිළිබඳ වැඩි විස්තර සඳහා පහත සඳහන් දෑ බලන්න:

මා පැවසූ පරිදි, යොමු කිරීමකට යොමු කිරීමක් කළ නොහැක. පහත වැඩසටහන උත්සාහ කරන්න:

#include <iostream>
using namespace std;

int main()
{
   int x = 10;
   int *ptr = &x;
   int &*ptr1 = ptr;
}

16

මට මේ කිසිවක් අවශ්‍ය නොවන්නේ නම් මම යොමු කිරීම් භාවිතා කරමි:

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

  • ඔබට දර්ශකයක් මත අංක ගණිතය කළ හැකිය. උදාහරණයක් වශයෙන්,p += offset;


5
යොමු ලෙස ප්‍රකාශයට පත් කළ &r + offsetස්ථානය ඔබට ලිවිය හැකියr
එම්එම්

15

කිසිවෙකු සඳහන් කර නැති මා දුටු දර්ශකයන් සහ යොමු කිරීම් අතර එක් මූලික වෙනසක් ඇත: යොමු තර්ක මඟින් ශ්‍රිත තර්ක වලදී පාස්-බයි-යොමු-අර්ථ නිරූපණයන් සක්‍රීය කරයි. දර්ශකයන්, එය මුලින් නොපෙනුනත්, නොපෙන්වයි: ඒවා ලබා දෙන්නේ වටිනාකමින් යුත් අර්ථකථන පමණි. මෙම ලිපියෙන් මෙය ඉතා සියුම් ලෙස විස්තර කර ඇත .

සුභ පැතුම්, & rzej


1
යොමු සහ දර්ශක දෙකම හැසිරවීම් වේ. ඔවුන් දෙදෙනාම ඔබට ඔබේ වස්තුව යොමු කිරීම මඟින් අර්ථ නිරූපණය කරයි , නමුත් හසුරුව පිටපත් කර ඇත. වෙනසක් නැත. (ශබ්දකෝෂයක සොයා බැලීම සඳහා යතුරක් වැනි හැසිරවීම් සඳහා වෙනත් ක්‍රම තිබේ)
බෙන් වොයිග්ට්

මමත් මේ වගේ හිතුවා. නමුත් එය එසේ නොවීමට හේතුව විස්තර කරන සම්බන්ධිත ලිපිය බලන්න.
ඇන්ඩ්‍රෙජ්

2
Nd ඇන්ඩ්‍රස්: එය මගේ අදහස් දැක්වීමේ තනි වාක්‍යයේ ඉතා දිගු අනුවාදයක් පමණි: හසුරුව පිටපත් කර ඇත.
බෙන් වොයිග්ට්

මට මේ ගැන වැඩි විස්තරයක් අවශ්‍යයි "හසුරුව පිටපත් කර ඇත". මට යම් මූලික අදහසක් වැටහී ඇති නමුත් භෞතිකව යොමු කිරීම සහ දර්ශකය යන දෙකම විචල්‍යයේ මතක පිහිටීම පෙන්වා දෙයි. එය අන්වර්ථය අගය විචල්‍යය ගබඩා කර විචල්‍යයේ අගය වෙනස් කිරීමක් හෝ වෙනත් දෙයක් ලෙස යාවත්කාලීන කරනවාද? මම නවකයෙක්, කරුණාකර එය මෝඩ ප්‍රශ්නයක් ලෙස සලකුණු නොකරන්න.
අසීම්

1
Nd ඇන්ඩ්‍රසෙජ් අසත්‍යය. අවස්ථා දෙකේදීම, පසු-අගය සිදුවෙමින් පවතී. යොමුව අගය මගින් ද, දර්ශකය අගය මගින් ද සම්මත වේ. වෙනත් ආකාරයකින් පැවසීම නවකයින් ව්‍යාකූල කරයි.
සැතපුම් මාර්ගය

14

ව්යාකූලත්වයට එකතු වීමේ අවදානමක, මට යම් ආදානයක් දැමීමට අවශ්යයි, එය බොහෝ දුරට රඳා පවතින්නේ සම්පාදකයා යොමු කිරීම් ක්රියාත්මක කරන ආකාරය මත බව මට විශ්වාසයි, නමුත් gcc සම්බන්ධයෙන් ගත් කල, යොමු කිරීමක් යොමු කළ හැක්කේ තොගයේ විචල්යයකට පමණි ඇත්ත වශයෙන්ම නිවැරදි නොවේ, උදාහරණයක් ලෙස මෙය ගන්න:

#include <iostream>
int main(int argc, char** argv) {
    // Create a string on the heap
    std::string *str_ptr = new std::string("THIS IS A STRING");
    // Dereference the string on the heap, and assign it to the reference
    std::string &str_ref = *str_ptr;
    // Not even a compiler warning! At least with gcc
    // Now lets try to print it's value!
    std::cout << str_ref << std::endl;
    // It works! Now lets print and compare actual memory addresses
    std::cout << str_ptr << " : " << &str_ref << std::endl;
    // Exactly the same, now remember to free the memory on the heap
    delete str_ptr;
}

මෙය ප්‍රතිදානය කරන්නේ:

THIS IS A STRING
0xbb2070 : 0xbb2070

මතක ලිපින පවා හරියටම සමාන බව ඔබ දුටුවහොත්, එයින් අදහස් වන්නේ යොමු කිරීම සාර්ථකව ගොඩවල් මත විචල්‍යයක් වෙත යොමු වන බවයි! දැන් ඔබට ඇත්තටම විකාරයක් වීමට අවශ්‍ය නම්, මෙයද ක්‍රියාත්මක වේ:

int main(int argc, char** argv) {
    // In the actual new declaration let immediately de-reference and assign it to the reference
    std::string &str_ref = *(new std::string("THIS IS A STRING"));
    // Once again, it works! (at least in gcc)
    std::cout << str_ref;
    // Once again it prints fine, however we have no pointer to the heap allocation, right? So how do we free the space we just ignorantly created?
    delete &str_ref;
    /*And, it works, because we are taking the memory address that the reference is
    storing, and deleting it, which is all a pointer is doing, just we have to specify
    the address with '&' whereas a pointer does that implicitly, this is sort of like
    calling delete &(*str_ptr); (which also compiles and runs fine).*/
}

මෙය ප්‍රතිදානය කරන්නේ:

THIS IS A STRING

එම නිසා යොමු දැක්වීමක් යනු හුඩ් යටතේ දර්ශකයක් වන අතර, ඔවුන් දෙදෙනාම මතක ලිපිනයක් ගබඩා කරමින් සිටිති, එහිදී ලිපිනය යොමු කිරීම අදාල නොවේ, මා සිතන්නේ std :: cout << str_ref; ඇමතුමෙන් පසු මකන්න & str_ref? හොඳයි, පැහැදිලිවම එය දඩ සම්පාදනය කරයි, නමුත් එය වලංගු විචල්‍යයක් වෙත තවදුරටත් යොමු නොවන නිසා ධාවන වේලාවේදී ඛණ්ඩනය වීමේ දෝෂයක් ඇති කරයි, අපට අවශ්‍යයෙන්ම බිඳුණු සඳහනක් තවමත් පවතී (එය විෂය පථයෙන් බැහැර වන තුරු), නමුත් නිෂ් .ල ය.

වෙනත් වචන වලින් කිවහොත්, යොමු කිරීමක් යනු දර්ශක යාන්ත්‍ර විද්‍යාව වියුක්ත කර ඇති අතර එය ආරක්ෂිත හා භාවිතයට පහසු කරයි (අහම්බෙන් දර්ශක ගණිතයක් නැත, මිශ්‍ර කිරීමක් නැත. 'සහ' -> ', ආදිය), ඔබ උපකල්පනය කරයි ඉහත මගේ උදාහරණ වැනි විකාර උත්සාහ නොකරන්න;)

දැන් සම්පාදකයෙකු යොමු කිරීම් හසුරුවන ආකාරය කුමක් වුවත් , එය සෑම විටම යම් ආකාරයක දර්ශකයක් යටින් පවතිනු ඇත , මන්ද එය අපේක්ෂිත පරිදි ක්‍රියා කිරීම සඳහා නිශ්චිත මතක ලිපිනයක නිශ්චිත විචල්‍යයක් වෙත යොමු කිරීමක් යොමු විය යුතු බැවින් මෙය වටා යෑමක් නොමැත (එබැවින් 'යොමු' යන පදය).

යොමු කිරීම් සමඟ මතක තබා ගත යුතු එකම ප්‍රධාන රීතිය නම්, ඒවා ප්‍රකාශ කරන අවස්ථාවේ දී නිර්වචනය කළ යුතු බවයි (ශීර්ෂ පා in යක සඳහනක් හැරුණු විට, එය ඉදිකිරීම්කරු තුළ අර්ථ දැක්විය යුතුය, එය අඩංගු වස්තුවෙන් පසුව එය නිර්වචනය කිරීමට ප්‍රමාද වැඩියි).

මතක තබා ගන්න, ඉහත මගේ උදාහරණ පමණක් වන අතර, යොමු දැක්වීමක් යනු කුමක්ද යන්න නිරූපණය කරන උදාහරණ, ඔබට කිසි විටෙකත් ඒ ආකාරයෙන් යොමු කිරීමක් භාවිතා කිරීමට අවශ්‍ය නොවනු ඇත! යොමුව නිසි ලෙස භාවිතා කිරීම සඳහා දැනටමත් නියපොතු හිසට පහර දෙන පිළිතුරු ඕනෑ තරම් තිබේ


14

තවත් වෙනසක් නම්, ඔබට අවලංගු වර්ගයකට දර්ශක තිබිය හැකි අතර (එයින් අදහස් කරන්නේ ඕනෑම දෙයකට දර්ශකය) නමුත් අවලංගු කිරීම සඳහා යොමු කිරීම තහනම්ය.

int a;
void * p = &a; // ok
void & p = a;  //  forbidden

මෙම සුවිශේෂී වෙනස ගැන මම සැබවින්ම සතුටු වන බව පැවසිය නොහැක. ලිපිනයකින් ඕනෑම දෙයකට අර්ථය යොමු කිරීමත්, වෙනත් ආකාරයකින් යොමු කිරීම් සඳහා එකම හැසිරීමත් එයට ඉඩ දෙනු ඇතැයි මම කැමැත්තෙමි. යොමු කිරීම් භාවිතා කරමින් memcpy වැනි C පුස්තකාල ක්‍රියාකාරකම්වල සමානකම් නිර්වචනය කිරීමට එය ඉඩ දෙයි.


13

එසේම, ආදාන කර ඇති ශ්‍රිතයක පරාමිතියක් වන යොමු කිරීමක් දර්ශකයකට වඩා වෙනස් ලෙස හැසිරවිය හැක.

void increment(int *ptrint) { (*ptrint)++; }
void increment(int &refint) { refint++; }
void incptrtest()
{
    int testptr=0;
    increment(&testptr);
}
void increftest()
{
    int testref=0;
    increment(testref);
}

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

ඇත්ත වශයෙන්ම, දර්ශකය සහ යොමු කිරීම නොබැඳි ශ්‍රිත සඳහා එකම කේතයක් ජනනය කරන අතර, ශ්‍රිතය විසින් වෙනස් කර ආපසු ලබා නොදුනහොත්, යොමු දැක්වීමට වඩා සහජයෙන්ම අගය අනුව සම්මත කිරීම වඩා හොඳය.


11

පරිශීලකයන් විසින් නිර්වචනය කරන ලද වර්ගයක පෙරනිමි තර්කයක් සැපයීම තවත් යොමුකිරීමේ තවත් රසවත් භාවිතයකි:

class UDT
{
public:
   UDT() : val_d(33) {};
   UDT(int val) : val_d(val) {};
   virtual ~UDT() {};
private:
   int val_d;
};

class UDT_Derived : public UDT
{
public:
   UDT_Derived() : UDT() {};
   virtual ~UDT_Derived() {};
};

class Behavior
{
public:
   Behavior(
      const UDT &udt = UDT()
   )  {};
};

int main()
{
   Behavior b; // take default

   UDT u(88);
   Behavior c(u);

   UDT_Derived ud;
   Behavior d(ud);

   return 1;
}

පෙරනිමි රසය යොමු කිරීම්වල 'තාවකාලික බැඳීමක් යොමු කිරීම' භාවිතා කරයි.


11

මෙම වැඩසටහන ප්‍රශ්නයේ පිළිතුර තේරුම් ගැනීමට උපකාරී වේ. මෙය "j" සහ "ptr" යන විචල්ය "x" වෙත යොමු කරන සරල වැඩසටහනකි.

#include<iostream>

using namespace std;

int main()
{
int *ptr=0, x=9; // pointer and variable declaration
ptr=&x; // pointer to variable "x"
int & j=x; // reference declaration; reference to variable "x"

cout << "x=" << x << endl;

cout << "&x=" << &x << endl;

cout << "j=" << j << endl;

cout << "&j=" << &j << endl;

cout << "*ptr=" << *ptr << endl;

cout << "ptr=" << ptr << endl;

cout << "&ptr=" << &ptr << endl;
    getch();
}

වැඩසටහන ක්‍රියාත්මක කර ප්‍රතිදානය දෙස බලන්න එවිට ඔබට වැටහෙනු ඇත.

එසේම, විනාඩි 10 ක් ඉතිරි කර මෙම වීඩියෝව නරඹන්න: https://www.youtube.com/watch?v=rlJrrGV0iOg


11

මෙහි ආවරණය නොවූ තවත් කරුණක් ඇති බව මට හැඟේ.

දර්ශකයන් මෙන් නොව, යොමු කිරීම් ඔවුන් යොමු කරන වස්තුවට කෘතීමව සමාන වේ , එනම් වස්තුවකට යෙදිය හැකි ඕනෑම මෙහෙයුමක් යොමු කිරීමක් සඳහා ක්‍රියා කරයි, සහ හරියටම එකම වාක්‍ය ඛණ්ඩය සමඟ (ව්‍යතිරේකය ඇත්ත වශයෙන්ම ආරම්භය වේ).

මෙය මතුපිටින් පෙනෙන්නට තිබුණද, C ++ විශේෂාංග ගණනාවක් සඳහා මෙම දේපල ඉතා වැදගත් යැයි මම විශ්වාස කරමි, උදාහරණයක් ලෙස:

  • සැකිලි . සැකිල්ල පරාමිතීන් තාරා-ටයිප් වන බැවින්, වර්ගයේ සින්ටැක්ටික් ගුණ සියලු කරුණු, බොහෝ විට එකම සැකිල්ල දෙකම සමග භාවිතා කල හැකි වේ Tහා T&.
    (හෝ std::reference_wrapper<T>එය තවමත් ව්‍යාජ වාත්තු කිරීමක් මත රඳා පවතී T&)
    දෙකම ආවරණය වන T&සහ T&&ඊටත් වඩා පොදු වන ආකෘති .

  • Lvalues . ප්රකාශය සලකා බලන්න str[0] = 'X';යොමු නොමැතිව එය ක්රියා කරන්නේ c-string ( char* str) සඳහා පමණි. යොමු දැක්වීමෙන් අක්‍ෂරය නැවත ලබා දීමෙන් පරිශීලක අර්ථ දක්වන පන්තිවලට එකම අංකනයක් තිබිය හැක.

  • ඉදිකිරීම්කරුවන් පිටපත් කරන්න . වාක්‍ය ඛණ්ඩ පිටපත් කිරීම සඳහා වස්තූන් යැවීම අර්ථවත් කරයි. නමුත් පිටපත් සාදන්නෙකුට වස්තුවක් වටිනාකමින් ගැනීමට ක්‍රමයක් නොමැත - එහි ප්‍රති result ලය වනුයේ එකම පිටපත් සාදන්නාට පුනරාවර්තන ඇමතුමකි. මෙහි ඇති එකම විකල්පය ලෙස මෙය යොමු කරයි.

  • ක්රියාකරු අධි බර පැටවීම . යොමු කිරීම් සමඟ ක්‍රියාකරු ඇමතුමකට operator+(const T& a, const T& b)ඉන්ඩෙක්ෂන් හඳුන්වා දිය හැකිය - කියන්න, එකම ඉන්ෆික්ස් අංකනය රඳවා ගනිමින්. නිතිපතා අධි බර පැටවූ කාර්යයන් සඳහාද මෙය ක්‍රියා කරයි.

මෙම කරුණු C ++ සහ සම්මත පුස්තකාලයේ සැලකිය යුතු කොටසක් බලගන්වයි, එබැවින් මෙය යොමු කිරීම්වල ප්‍රධාන දේපලකි.


" ව්‍යංග වාත්තු " වාත්තු යනු වාක්‍ය ඛණ්ඩයකි, එය ව්‍යාකරණ තුළ පවතී; කාස්ට් සෑම විටම පැහැදිලිය
කුතුහලයෙන්

9

සමහර විට සමහර රූපක උපකාරී වනු ඇත; ඔබගේ ඩෙස්ක්ටොප් තිර අවකාශයේ සන්දර්භය තුළ -

  • යොමුවකට සත්‍ය කවුළුවක් නියම කිරීම අවශ්‍ය වේ.
  • දර්ශකයකට තිරයේ ඇති ඉඩ කැබැල්ලක පිහිටීම අවශ්‍ය වන අතර එම කවුළු වර්ගයේ අවස්ථා ශුන්‍ය හෝ වැඩි ගණනක් අඩංගු වනු ඇතැයි ඔබ සහතික කරයි.

9

දර්ශකයන් සහ යොමු කිරීම් අතර ඉතා වැදගත් තාක්‍ෂණික නොවන වෙනසක් ඇත: ශ්‍රිතයක් වෙත යොමු කරන ලද තර්කයක්, නියත නොවන යොමු කිරීමකින් ශ්‍රිතයකට සම්මත කරන ලද තර්කයකට වඩා දෘශ්‍යමාන වේ. උදාහරණයක් වශයෙන්:

void fn1(std::string s);
void fn2(const std::string& s);
void fn3(std::string& s);
void fn4(std::string* s);

void bar() {
    std::string x;
    fn1(x);  // Cannot modify x
    fn2(x);  // Cannot modify x (without const_cast)
    fn3(x);  // CAN modify x!
    fn4(&x); // Can modify x (but is obvious about it)
}

නැවත සී වෙත, ඇමතුමක් ලබා fn(x)දිය හැක්කේ වටිනාකමෙන් පමණක් බැවින් එය අනිවාර්යයෙන්ම වෙනස් කළ නොහැක x; තර්කයක් වෙනස් කිරීමට ඔබට දර්ශකයක් සමත් විය යුතුය fn(&x). එබැවින් තර්කයක් කලින් ඉදිරිපත් නොකළේ නම් &එය වෙනස් නොවන බව ඔබ දැන සිටියේය. (සංවාදය, &නවීකරණය කරන ලද, සත්‍ය නොවේ, මන්ද ඔබට සමහර විට constදර්ශක මඟින් කියවීමට පමණක් විශාල ව්‍යුහයන් පසු කිරීමට සිදුවනු ඇත .)

සමහරු තර්ක කරන්නේ කේතය කියවීමේදී මෙය එතරම් ප්‍රයෝජනවත් අංගයක් වන constඅතර, ශ්‍රිතය කිසි විටෙකත් අපේක්ෂා නොකළද, යොමු නොවන පරාමිතීන් සඳහා යොමු පරාමිතීන් සඳහා යොමු දර්ශක පරාමිතීන් සැමවිටම භාවිතා කළ යුතුය nullptr. එනම්, fn3()ඉහත සඳහන් පරිදි ක්‍රියාකාරී අත්සන් වලට ඉඩ නොදිය යුතු යැයි එම පුද්ගලයින් තර්ක කරති . ගූගල් හි සී ++ විලාසිතාවේ මාර්ගෝපදේශ මේ සඳහා උදාහරණයකි.


7

දර්ශකය සහ යොමු කිරීම අතර වෙනස

දර්ශකයක් 0 ට ආරම්භ කළ හැකි අතර යොමු කිරීමක් නොවේ. ඇත්ත වශයෙන්ම, යොමු කිරීමක් වස්තුවකට යොමු විය යුතුය, නමුත් දර්ශකයක් ශුන්‍ය දර්ශකය විය හැකිය:

int* p = 0;

නමුත් අපි කළ නොහැකි int& p = 0;ද සහ int& p=5 ;.

ඇත්ත වශයෙන්ම එය නිසියාකාරව සිදු කිරීම සඳහා, අපි මුලින් වස්තුවක් ප්‍රකාශයට පත් කර නිර්වචනය කර තිබිය යුතුය, එවිට අපට එම වස්තුව ගැන සඳහනක් කළ හැකිය, එබැවින් පෙර කේතය නිවැරදිව ක්‍රියාත්මක කිරීම වනුයේ:

Int x = 0;
Int y = 5;
Int& p = x;
Int& p1 = y;

තවත් වැදගත් කරුණක් නම්, අපට ආරම්භකය නොමැතිව දර්ශකය ප්‍රකාශයට පත් කළ හැකි නමුත්, යොමු කිරීමේදී එවැනි දෙයක් කළ නොහැකි අතර එය සෑම විටම විචල්‍ය හෝ වස්තුවකට යොමු කිරීමක් කළ යුතුය. කෙසේ වෙතත්, එවැනි දර්ශකයක් භාවිතා කිරීම අවදානම් සහගත බැවින් සාමාන්‍යයෙන් අපි පරීක්‍ෂා කරන්නේ දර්ශකය ඇත්ත වශයෙන්ම යම් දෙයකට යොමු වී ඇත්ද යන්නයි. යොමු කිරීමකදී එවැනි චෙක්පතක් අවශ්‍ය නොවේ, මන්ද ප්‍රකාශ කිරීමේදී වස්තුවක් යොමු කිරීම අනිවාර්ය බව අපි දැනටමත් දනිමු.

තවත් වෙනසක් නම්, දර්ශකයට වෙනත් වස්තුවකට යොමු විය හැකි නමුත් යොමු කිරීම සෑම විටම එකම වස්තුවකට යොමු වේ, අපි මෙම උදාහරණය ගනිමු:

Int a = 6, b = 5;
Int& rf = a;

Cout << rf << endl; // The result we will get is 6, because rf is referencing to the value of a.

rf = b;
cout << a << endl; // The result will be 5 because the value of b now will be stored into the address of a so the former value of a will be erased

තවත් කරුණක්: අපට එස්.ටී.එල් අච්චුවක් වැනි අච්චුවක් ඇති විට, එවැනි පන්ති අච්චුවක් සෑම විටම යොමු කිරීමක් මිස දර්ශකයක් නොව, ක්‍රියාකරු භාවිතයෙන් පහසුවෙන් කියවීමට හෝ නව වටිනාකමක් ලබා දීමට []:

Std ::vector<int>v(10); // Initialize a vector with 10 elements
V[5] = 5; // Writing the value 5 into the 6 element of our vector, so if the returned type of operator [] was a pointer and not a reference we should write this *v[5]=5, by making a reference we overwrite the element by using the assignment "="

1
අපට තවමත් තිබිය හැකිය const int& i = 0.
Revolver_Ocelot

1
මෙම අවස්ථාවෙහිදී යොමු කිරීම කියවීමේදී පමණක් භාවිතා කරනු ඇත. අපට "const_cast" භාවිතා කරමින් පවා මෙම සංයුක්ත යොමුව වෙනස් කළ නොහැක.
dhokar.w

1
const_cast යොමු කිරීම් සමඟ හොඳින් ක්‍රියා කරයි: coliru.stacked-crooked.com/a/eebb454ab2cfd570
Revolver_Ocelot

1
ඔබ යොමු කිරීමක් සඳහා වාත්තු කිරීමක් කරන්නේ මෙය යොමු කිරීමට උත්සාහ නොකරන්න; const int & i =; const_cast <int> (i); යොමු කිරීම සඳහා නව වටිනාකමක් ලිවීමට හා පැවරීමට හැකි වන පරිදි මම විමර්ශනයේ ස්ථායීතාවය ඉවත දැමීමට උත්සාහ කරමි, නමුත් මෙය කළ නොහැකි ය. කරුණාකර අවධානය යොමු කරන්න !!
dhokar.w

6

වෙනස වන්නේ ක්‍රමලේඛ ක්‍රියාත්මක කිරීමේදී යම් වේලාවක නියත නොවන දර්ශක විචල්‍යය (නියතයට දර්ශකයක් සමඟ පටලවා නොගත යුතුය) වෙනස් කළ හැකි අතර, දර්ශක අර්ථ නිරූපණයන් භාවිතා කිරීම අවශ්‍ය වේ (&, *) ක්‍රියාකරුවන් වන අතර ආරම්භයේදී යොමු කිරීම් සැකසිය හැකිය. පමණක් (ඔබට ඒවා ඉදිකිරීම් ආරම්භක ලැයිස්තුවේ පමණක් සැකසිය හැකිය, නමුත් වෙනත් ආකාරයකින් නොවේ) සහ අර්ථ නිරූපණයට ප්‍රවේශ වන සාමාන්‍ය අගය භාවිතා කරන්න. මම ඉතා පැරණි පොතක කියවා ඇති පරිදි ක්‍රියාකරුවන් අධික ලෙස පැටවීම සඳහා සහය දැක්වීම සඳහා මූලික වශයෙන් යොමු කිරීම් හඳුන්වා දෙන ලදී. මෙම ත්‍රෙඩ් එකේ කවුරුහරි ප්‍රකාශ කර ඇති පරිදි - දර්ශකය 0 හෝ ඔබට අවශ්‍ය ඕනෑම අගයකට සැකසිය හැකිය. 0 (NULL, nullptr) යන්නෙන් අදහස් කරන්නේ දර්ශකය කිසිවක් නොමැතිව ආරම්භ කර ඇති බවයි. ශුන්‍ය දර්ශකය විරූපණය කිරීම දෝෂයකි. නමුත් ඇත්ත වශයෙන්ම දර්ශකයේ යම් නිවැරදි මතක ස්ථානයකට යොමු නොවන අගයක් අඩංගු විය හැකිය. ඔබ සැමවිටම නිවැරදි වර්ගයේ අගයක් ලබා දෙන හෙයින්, යොමු කළ නොහැකි දෙයකට යොමු කිරීමක් ආරම්භ කිරීමට පරිශීලකයාට ඉඩ නොදීමට ඔවුන්ගේ වාර්‍තා උත්සාහ කරයි. යොමු විචල්‍යය වැරදි මතක ස්ථානයකට ගෙන ඒමට බොහෝ ක්‍රම තිබුණත් - මෙය ගැඹුරින් හාරා නොගැනීම හොඳය. යන්ත්‍ර මට්ටමින් දර්ශකය සහ යොමු දෙකම එකසේ ක්‍රියාත්මක වේ - දර්ශකයන් හරහා. අත්යවශ්ය යොමුවලින් කියමු සින්ටැක්ටික් සීනි. rvalue යොමු කිරීම් මෙයට වෙනස් වේ - ඒවා ස්වාභාවිකවම සිරස් / ගොඩවල් වස්තු වේ. යොමු විචල්‍යය වැරදි මතක ස්ථානයකට ගෙන ඒමට බොහෝ ක්‍රම තිබුණත් - මෙය ගැඹුරින් හාරා නොගැනීම හොඳය. යන්ත්‍ර මට්ටමින් දර්ශකය සහ යොමු දෙකම එකසේ ක්‍රියාත්මක වේ - දර්ශකයන් හරහා. අත්යවශ්ය යොමුවලින් කියමු සින්ටැක්ටික් සීනි. rvalue යොමු කිරීම් මෙයට වෙනස් වේ - ඒවා ස්වාභාවිකවම සිරස් / ගොඩවල් වස්තු වේ. යොමු විචල්‍යය වැරදි මතක ස්ථානයකට ගෙන ඒමට බොහෝ ක්‍රම තිබුණත් - මෙය ගැඹුරින් හාරා නොගැනීම හොඳය. යන්ත්‍ර මට්ටමින් දර්ශකය සහ යොමු දෙකම එකසේ ක්‍රියාත්මක වේ - දර්ශකයන් හරහා. අත්යවශ්ය යොමුවලින් කියමු සින්ටැක්ටික් සීනි. rvalue යොමු කිරීම් මෙයට වෙනස් වේ - ඒවා ස්වාභාවිකවම සිරස් / ගොඩවල් වස්තු වේ.


5

සරල වචන වලින් කිවහොත්, අපට යොමු දැක්වීමක් විචල්‍යයක විකල්ප නමක් වන අතර, දර්ශකය යනු වෙනත් විචල්‍යයක ලිපිනය රඳවා ගන්නා විචල්‍යයකි. උදා

int a = 20;
int &r = a;
r = 40;  /* now the value of a is changed to 40 */

int b =20;
int *ptr;
ptr = &b;  /*assigns address of b to ptr not the value */
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.