යොමුව සින්ටැක්ටික් සීනි බව මම දනිමි, එබැවින් කේතය කියවීමට හා ලිවීමට පහසුය.
නමුත් වෙනස්කම් මොනවාද?
int &x = *(int*)0;
gcc මත. යොමු කිරීම ඇත්ත වශයෙන්ම NULL වෙත යොමු කළ හැකිය.
යොමුව සින්ටැක්ටික් සීනි බව මම දනිමි, එබැවින් කේතය කියවීමට හා ලිවීමට පහසුය.
නමුත් වෙනස්කම් මොනවාද?
int &x = *(int*)0;
gcc මත. යොමු කිරීම ඇත්ත වශයෙන්ම NULL වෙත යොමු කළ හැකිය.
Answers:
දර්ශකයක් නැවත පැවරිය හැකිය:
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;
දර්ශකයට එහි මතක ලිපිනය සහ ප්රමාණය (x86 මත බයිට් 4) ඇත, නමුත් යොමු කිරීමක් එකම මතක ලිපිනය (මුල් විචල්යය සමඟ) බෙදා ගන්නා අතර තොගයේ යම් ඉඩක් ගනී. යොමුවකට මුල් විචල්යයට සමාන ලිපිනයක් ඇති බැවින්, එකම විචල්යයේ වෙනත් නමක් ලෙස යොමු කිරීමක් සිතීම ආරක්ෂිත වේ. සටහන: තොගයේ හෝ ගොඩවල තිබිය හැකි දර්ශකය කුමක්ද? ඩිටෝ යොමු කිරීමක්. මෙම ප්රකාශයේ මගේ ප්රකාශය වන්නේ දර්ශකයක් තොගයට යොමු කළ යුතු බව නොවේ. දර්ශකය යනු මතක ලිපිනයක් ඇති විචල්යයකි. මෙම විචල්යය තොගයේ ඇත. යොමුවකට තොගයේ තමන්ගේම ඉඩක් ඇති හෙයින් සහ ලිපිනය විචල්යයට සමාන බැවින් එය යොමු කරයි. ගොඩවල් එදිරිව ගොඩවල් මත තවත්. මෙයින් ගම්ය වන්නේ සම්පාදකයා ඔබට නොකියන යොමුවක සැබෑ ලිපිනයක් ඇති බවයි.
int x = 0;
int &r = x;
int *p = &x;
int *p2 = &r;
assert(p == p2);
ඔබට අමතර මට්ටමේ අවිනිශ්චිතතාවයන් ලබා දෙන දර්ශකයන්ට දර්ශක සිට දර්ශක දක්වා විය හැකිය. යොමු දැක්වීම් ඉදිරිපත් කරන්නේ එක් මට්ටමේ අවිනිශ්චිතතාවයක් පමණි.
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);
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
දර්ශකයන්ට අරාව හරහා නැවත යෙදිය හැකිය; ඔබට ++
දර්ශකයක් යොමු කරන ඊළඟ අයිතමය + 4
වෙත යාමට සහ 5 වන අංගයට යාමට භාවිතා කළ හැකිය. දර්ශකය පෙන්වා දෙන වස්තුව කොතරම් විශාල වුවත් මෙය වැදගත් නොවේ.
එය යොමු *
කරන මතක ස්ථානයට ප්රවේශ වීම සඳහා දර්ශකයක් අවලංගු කළ යුතු අතර, යොමු කිරීමක් කෙලින්ම භාවිතා කළ හැකිය. පංතියකට / ව්යුහයකට දර්ශකයක් ->
එහි සාමාජිකයින්ට ප්රවේශ වීම සඳහා භාවිතා කරන අතර යොමු කිරීමක් භාවිතා කරයි .
.
යොමු දැක්වීම් අරාවකට පුරවා ගත නොහැකි අතර, දර්ශකයන් විය හැකි අතර (පරිශීලක it ලිට්බ් විසින් සඳහන් කර ඇත)
නිරන්තර යොමු කිරීම් තාවකාලික වලට බැඳිය හැකිය. දර්ශකයන්ට නොහැක (කිසියම් අවිනිශ්චිතතාවයකින් තොරව):
const int &x = int(12); //legal C++
int *y = &int(12); //illegal to dereference a temporary.
මෙය const&
තර්ක ලැයිස්තුවේ සහ වෙනත් දේ සඳහා ආරක්ෂිත වේ.
ඒ සඳහනක් ලෙස කල්පනා කළ හැකි නිරන්තර අවධානය යොමුකළ සම්පාදකවරයා වන අයදුම් කරනු ඇත (! නියත අගය කිරීමට අවධානය යොමුකළ සමඟ පටලවා නොගත) ස්වයංක්රීය indirection සමග, එනම් *
ඔබ වෙනුවෙන් ක්රියාකරු.
සියලුම යොමු කිරීම් ශුන්ය නොවන අගයකින් ආරම්භ කළ යුතුය, නැතහොත් සම්පාදනය අසාර්ථක වනු ඇත. විමර්ශනයක ලිපිනය ලබා ගත නොහැක - ලිපින ක්රියාකරු ඒ වෙනුවට යොමු කළ අගයෙහි ලිපිනය නැවත ලබා දෙනු ඇත - යොමු කිරීම් මත අංක ගණිතය කිරීමට ද නොහැකිය.
C ක්රමලේඛකයින් C ++ යොමු කිරීම් වලට අකමැති විය හැකි බැවින් එය අවිනිශ්චිතතාවයක් සිදු වූ විට හෝ ශ්රිත අත්සන් දෙස නොබලා තර්කයක් වටිනාකමින් හෝ දර්ශකයකින් සම්මත වුවහොත් එය තවදුරටත් පැහැදිලි නොවනු ඇත.
C ++ ක්රමලේඛකයින් අනාරක්ෂිත යැයි සලකන බැවින් දර්ශක භාවිතා කිරීමට අකමැති විය හැකිය - බොහෝ සුළු කාරණා හැරුණු විට නියත දර්ශකයන්ට වඩා යොමු කිරීම් සැබවින්ම ආරක්ෂිත නොවේ - ස්වයංක්රීය නිරෝධනය කිරීමේ පහසුව සහ වෙනස් අර්ථකථන අර්ථයක් ඇත.
C ++ නිති අසන ප්රශ්න වලින් පහත ප්රකාශය සලකා බලන්න :
යටින් පවතින assembly භාෂාවෙන් ලිපිනයක් භාවිතා කර සඳහනක් බොහෝ විට ක්රියාත්මක වුවත්, කරුණාකර නොවන වස්තුවක් සඳහා මාර ලස්සන පහිටුම් දක්වනය ලෙස සඳහනක් හිතන්න. යොමු කිරීම යනු වස්තුවයි. එය වස්තුවට දර්ශකයක් හෝ වස්තුවක පිටපතක් නොවේ. එය වේ වස්තුව.
නමුත් යොමු කිරීමක් ඇත්ත වශයෙන්ම වස්තුව නම්, අන්තරාදායක යොමු කිරීම් තිබිය හැක්කේ කෙසේද? කළමනාකරණය නොකළ භාෂාවල, යොමු කිරීම් දර්ශකයන්ට වඩා 'ආරක්ෂිත' වීම කළ නොහැක්කකි - සාමාන්යයෙන් විෂය පථයේ සීමාවන් හරහා අන්වර්ථ අගයන් විශ්වාසදායක ලෙස වෙනස් කිරීමට ක්රමයක් නොමැත!
සී පසුබිම සිට පැමිණෙන, C ++ යොමු තරමක් මෝඩ සංකල්පය වගේ විය හැක, නමුත් එක තවමත් සූචක හැකි නම් වෙනුවට ඔවුන් භාවිතා කළ යුතු: ස්වයංක්රීය indirection වේ පහසු, සහ සමඟ කටයුතු කරන විට යොමු විශේෂයෙන්ම ප්රයෝජනවත් වී RAII - නිසා ඕනෑම දකින්නේ ආරක්ෂාව නමුත් වාසිය, නමුත් ඔවුන් මුග්ධ කේත ලිවීම අඩු අමුතු නිසා.
RAII යනු C ++ හි කේන්ද්රීය සංකල්පවලින් එකකි, නමුත් එය අර්ථකථන පිටපත් කිරීම සමඟ සුළු වශයෙන් අන්තර්ක්රියා කරයි. පිටපත් කිරීමකට සම්බන්ධ නොවන බැවින් වස්තු යොමු කිරීම මඟින් මෙම ගැටළු මඟහරවා ගත හැකිය. භාෂාවේ යොමු කිරීම් නොතිබුනේ නම්, ඒ වෙනුවට ඔබට දර්ශක භාවිතා කිරීමට සිදුවනු ඇත, ඒවා භාවිතා කිරීමට වඩා කරදරකාරී වන අතර එමඟින් භාෂා සැලසුම් මූලධර්මය උල්ලං ting නය කරමින් විකල්පයන්ට වඩා හොඳ-ප්රායෝගික විසඳුම පහසු විය යුතුය.
ඔබට සැබවින්ම ව්යාකූල වීමට අවශ්ය නම්, ඔබට දර්ශකයක් සමඟ කළ නොහැකි සඳහනක් සමඟ ඔබට කළ හැකි එක් දෙයක් තිබේ: තාවකාලික වස්තුවක ආයු කාලය දීර් 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
එය සම්පාදනය කිරීමට අසමත් විය යුතුය. ඔබට තාවකාලික වස්තුවකට නොනවතින සඳහනක් බැඳ තැබිය නොහැක, එම කාරණය සඳහා එහි ලිපිනය ගත නොහැක.
const &
බන්ධනයේ සත්යතාවයෙන් වන අතර , යොමු කිරීම විෂය පථයෙන් බැහැර වූ විට පමණක් සත්ය යොමු කරන ලද වර්ගය විනාශ කරන්නා ලෙස හැඳින්වේ (යොමු වර්ගයට සාපේක්ෂව එය පදනමක් විය හැකිය). එය යොමු කිරීමක් බැවින්, ඒ අතර කිසිදු පෙත්තක් සිදු නොවේ.
Animal x = fast ? getHare() : getTortoise()
එසේ නම් x
සම්භාව්ය යසිකා, ගැටළුව, මුහුණ දෙනු ඇත අතර, Animal& x = ...
නිවැරදිව වැඩ කරනු ඇත.
මීට අමතරව සින්ටැක්ටික් සීනි සිට, අදාල නම් වේ const
දර්ශකයක් ( නැති වූ පෙන්නුම් කරන්නක් const
). ඔබ විමර්ශන විචල්යය ප්රකාශ කරන විට එය යොමු කරන දේ ඔබ විසින් ස්ථාපිත කළ යුතු අතර ඔබට පසුව එය වෙනස් කළ නොහැක.
යාවත්කාලීන කිරීම: දැන් මම ඒ ගැන තවත් සිතන විට වැදගත් වෙනසක් ඇත.
කොන්ස්ට් පොයින්ටරයක ඉලක්කය එහි ලිපිනය ගෙන කොන්ස්ට් කාස්ට් භාවිතා කිරීමෙන් ප්රතිස්ථාපනය කළ හැකිය.
යොමුවක ඉලක්කය යූබී හි කිසිදු ආකාරයකින් ප්රතිස්ථාපනය කළ නොහැක.
මෙය සම්පාදකයාට යොමු කිරීමක් මත වඩාත් ප්රශස්තිකරණය කිරීමට අවසර දිය යුතුය.
T* const
ඇත්තේ වෙනස් සින්ටැක්ටික් සීනි සහිත (එය සිදුවන්නේ * සහ ඔබේ කේතයෙන් බොහෝ දේ ඉවත් කිරීමට ය).
int i; int const *pci = &i; /* implicit conv to const int* */ int *pi = const_cast<int*>(pci);
හරි.
ජනප්රිය මතයට පටහැනිව, 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));
වඩා හොඳ ලිවීමේ කුසලතා ඇති අයෙකුගෙන් මෙම ගැටළුව පැරණි ලෙස බැලීමට, ජිම් හයිස්ලොප් සහ ඔසු සූටර්ගේ ශූන්ය යොමු බලන්න .
ශුන්ය දර්ශකයක් අවලංගු කිරීමේ අන්තරායන් පිළිබඳ තවත් උදාහරණයක් සඳහා රේමන්ඩ් චෙන් විසින් වෙනත් වේදිකාවක් වෙත කේතය ගෙනයාමට උත්සාහ කරන විට නිර්වචනය නොකළ හැසිරීම හෙළිදරව් කිරීම බලන්න .
ඔබට වඩාත්ම වැදගත් කොටස අමතක විය:
පොයින්ටර්ස් සමඟ ->
සාමාජික ප්රවේශය පරිශීලක යොමු ප්රවේශය සමඟ සාමාජික ප්රවේශය භාවිතා කරයි.
foo.bar
වන පැහැදිලිව වඩා උසස් foo->bar
කරන ආකාරයට vi වන පැහැදිලිව වඩා උසස් හැරදමයි :-)
->
දර්ශකය වෙත යොමු කිරීම සඳහා සපයයි.
.
සහ ->
vi සහ emacs සමඟ යම් සම්බන්ධයක් තිබේ :)
.
කිරීමට වඩා හොඳ යැයි මම සිතමි ->
, නමුත් vi vs emacs මෙන්, එය මුළුමනින්ම ආත්මීය වන අතර ඔබට කිසිවක් ඔප්පු කළ නොහැක
යොමු කිරීම් දර්ශකයන්ට බෙහෙවින් සමාන ය, නමුත් ඒවා විශේෂයෙන් සකසා ඇත්තේ සම්පාදකයින් ප්රශස්තිකරණය කිරීම සඳහා උපකාරී වේ.
උදාහරණයක් ලෙස:
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
කිරීම සැලකිය යුතු තරම් පහසුය.
void maybeModify(int& x) { 1[&x]++; }
ඉහත සඳහන් අනෙක් අදහස් සාකච්ඡා කරමින් සිටින අයෙකු යල්පැනගිය අදහස් දැක්වීමක් වැරදියට සලකුණු කළ බව මට හැඟේ
ඇත්ත වශයෙන්ම, යොමු කිරීමක් ඇත්ත වශයෙන්ම දර්ශකයක් මෙන් නොවේ.
සම්පාදකයෙකු විචල්යයන්ට “යොමු” තබා, මතක ලිපිනයක් සමඟ නමක් සම්බන්ධ කරයි; සම්පාදනය කිරීමේදී ඕනෑම විචල්ය නාමයක් මතක ලිපිනයකට පරිවර්තනය කිරීම එහි කාර්යය වේ.
ඔබ යොමු කිරීමක් සාදන විට, ඔබ සම්පාදකයාට පවසන්නේ ඔබ දර්ශක විචල්යයට වෙනත් නමක් ලබා දෙන බවයි; විචල්යයක් විය නොහැකි අතර එසේ නොවිය හැකි නිසා යොමු කිරීම් “ශුන්යයට යොමු කළ නොහැක”.
දර්ශකයන් විචල්ය වේ; ඒවායේ වෙනත් විචල්යයක ලිපිනය අඩංගු වේ, නැතහොත් ශුන්ය විය හැකිය. වැදගත් දෙය නම්, දර්ශකයට වටිනාකමක් ඇති අතර, යොමු කිරීමකට ඇත්තේ එය යොමු කරන විචල්යයක් පමණි.
දැන් සැබෑ කේතය පිළිබඳ යම් පැහැදිලි කිරීමක්:
int a = 0;
int& b = a;
මෙන්න ඔබ පෙන්වා දෙන වෙනත් විචල්යයක් නිර්මාණය නොකරයි a
; ඔබ අගය මතකයේ අන්තර්ගතයට තවත් නමක් එක් කරයි a
. මෙම මතකය දැන් නම් දෙකක් ඇති a
අතර b
, එය ඕනෑම නමකින් ආමන්ත්රණය කළ හැකිය.
void increment(int& n)
{
n = n + 1;
}
int a;
increment(a);
ශ්රිතයක් අමතන විට, සම්පාදකයා සාමාන්යයෙන් තර්ක පිටපත් කිරීම සඳහා මතක අවකාශයන් ජනනය කරයි. ශ්රිත අත්සන මඟින් නිර්මාණය කළ යුතු අවකාශයන් නිර්වචනය කර මෙම අවකාශයන් සඳහා භාවිතා කළ යුතු නම ලබා දෙයි. පරාමිතියක් යොමු කිරීමක් ලෙස ප්රකාශ කිරීමෙන් සම්පාදකයාට ක්රම ඇමතුම අතරතුර නව මතක ඉඩක් වෙන් කිරීම වෙනුවට ආදාන විචල්ය මතක අවකාශය භාවිතා කරන ලෙස පවසයි. ඔබේ ශ්රිතය ඇමතුම් විෂය පථයේ ප්රකාශිත විචල්යයක් සෘජුවම හසුරුවනු ඇතැයි පැවසීම අමුතු දෙයක් ලෙස පෙනේ, නමුත් සංයුක්ත කේතය ක්රියාත්මක කිරීමේදී වැඩි විෂය පථයක් නොමැති බව මතක තබා ගන්න; සරල පැතලි මතකයක් පමණක් ඇති අතර ඔබේ ශ්රිත කේතයට ඕනෑම විචල්යයන් හැසිරවිය හැකිය.
බාහිර විචල්යයක් භාවිතා කරන විට මෙන් සම්පාදනය කිරීමේදී ඔබේ සම්පාදකයාට විමර්ශනය දැන ගැනීමට නොහැකි විය හැකි අවස්ථා දැන් තිබේ. එබැවින් යටි කේතයේ දර්ශකයක් ලෙස යොමු කිරීමක් ක්රියාත්මක කිරීමට හෝ නොවීමට ඉඩ ඇත. නමුත් මම ඔබට දුන් උදාහරණ වලදී, එය බොහෝ විට දර්ශකයක් සමඟ ක්රියාත්මක නොවනු ඇත.
යොමු කිරීමක් කිසි විටෙකත් විය නොහැකිය NULL
.
void Foo::bar() { virtual_baz(); }
එම සෙග්ෆෝල්ට් වැනි කේත ඇත. යොමු කිරීම් අහෝසි විය හැකි බව ඔබ නොදන්නේ නම්, ඔබට ශුන්යය එහි මූලාරම්භය දක්වා සොයාගත නොහැක.
int &r=*p;
යනු නිර්වචනය නොකළ හැසිරීමකි. එම අවස්ථාවේදී, ඔබට “NULL වෙත යොමු කරන යොමු කිරීමක්” නොමැත, ඔබට කිසිසේත් තර්කානුකූල කළ නොහැකි
වෙනත් අගයකට වක්රව ප්රවේශ වීම සඳහා යොමු සහ දර්ශක යන දෙකම භාවිතා කරන අතර, යොමු සහ දර්ශක අතර වැදගත් වෙනස්කම් දෙකක් තිබේ. පළමුවැන්න නම්, යොමු කිරීමක් සෑම විටම වස්තුවකට යොමු වීමයි: එය ආරම්භයක් නොමැතිව යොමු කිරීමක් අර්ථ දැක්වීම දෝෂයකි. පැවරුමේ හැසිරීම දෙවන වැදගත් වෙනස වේ: යොමු කිරීමකට පැවරීම යොමු කිරීම බැඳී ඇති වස්තුව වෙනස් කරයි; එය වෙනත් වස්තුවක් වෙත යොමු කිරීම ප්රතික්ෂේප නොකරයි. ආරම්භ කිරීමෙන් පසු, යොමු කිරීමක් සෑම විටම එකම යටින් පවතින වස්තුවට යොමු වේ.
මෙම වැඩසටහන් කොටස් දෙක සලකා බලන්න. පළමුවෙන්ම, අපි එක් දර්ශකයක් තවත් දර්ශකයකට පවරමු:
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 වෙනස් කරයි, රී විසින් යොමු කරන ලද අගය මිස යොමු කිරීමම නොවේ. පැවරුමෙන් පසුව, යොමු දෙක තවමත් ඒවායේ මුල් වස්තූන් වෙත යොමු වන අතර, එම වස්තූන්ගේ වටිනාකම දැන් සමාන වේ.
වියුක්ත හෝ ශාස්ත්රීය ආකාරයකින් පරිගණක භාෂා හැදෑරීමට ඔබ හුරු නැතිනම් අර්ථාන්විත වෙනසක් ඇත.
ඉහළම මට්ටමේ දී, යොමු දැක්වීමේ අදහස නම් ඒවා විනිවිද පෙනෙන "අන්වර්ථයන්" ය. ඔබේ පරිගණකය ඒවා ක්රියාත්මක කිරීම සඳහා ලිපිනයක් භාවිතා කළ හැකි නමුත් ඔබ ඒ ගැන කරදර විය යුතු නැත: ඔබ ඒවා පවතින වස්තුවක් සඳහා “තවත් නමක්” ලෙස සිතිය යුතු අතර සින්ටැක්ස් එය පිළිබිඹු කරයි. ඒවා දර්ශකයන්ට වඩා දැඩි බැවින් ඔබ කම්පනකාරී යොමු කිරීමක් සෑදීමට සූදානම් වන විට ඔබේ කම්පයිලරයට වඩාත් විශ්වාසදායක ලෙස අනතුරු ඇඟවිය හැකිය.
ඉන් ඔබ්බට, ඇත්ත වශයෙන්ම දර්ශකයන් සහ යොමු කිරීම් අතර යම් ප්රායෝගික වෙනස්කම් තිබේ. ඒවා භාවිතා කිරීම සඳහා වන වාක්ය ඛණ්ඩය පැහැදිලිවම වෙනස් වන අතර, ඔබට “නැවත ආසන” යොමු කළ නොහැක, කිසිවක් ගැන සඳහනක් නැත, හෝ යොමු කිරීම් සඳහා යොමු කිරීම් තිබිය නොහැක.
යොමු කිරීම වෙනත් විචල්යයක් සඳහා අන්වර්ථයක් වන අතර දර්ශකය විචල්යයක මතක ලිපිනය දරයි. සම්මතයන් සාමාන්යයෙන් ශ්රිත පරාමිතීන් ලෙස භාවිතා කරයි, එවිට සම්මත වස්තුව පිටපත නොව වස්තුවම වේ.
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.
ඔබට ගතවන ඕනෑම අවකාශයක කිසිදු අතුරු ආබාධයක් (කේත ක්රියාත්මක නොකර) ඔබට සැබවින්ම දැකිය නොහැකි බැවින් එය කොපමණ ඉඩ ප්රමාණයක් ගත යුතුද යන්න ගැටළුවක් නොවේ.
අනෙක් අතට, යොමු කිරීම් සහ දර්ශකයන් අතර ඇති එක් ප්රධාන වෙනසක් නම්, නියත යොමු කිරීම් විෂය පථයෙන් බැහැර වන තුරු, නියත යොමු කිරීම් සඳහා පවරා ඇති තාවකාලිකයන් සජීවීව පැවතීමයි.
උදාහරණයක් වශයෙන්:
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 වැඩ කිරීමට ඉඩ දෙන භාෂා යාන්ත්රණය මෙයයි.
මෙය නිබන්ධනය මත පදනම් වේ . ලියා ඇති දෙයින් එය වඩාත් පැහැදිලි වේ:
>>> 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
.
nullptr
කරනවාද? ඔබ ඇත්තටම මෙම ත්රෙඩ් එකේ වෙනත් කොටසක් කියවා තිබේද, නැත්නම් ...?
යොමු කිරීම යනු යම් මතකයකට ලබා දෙන තවත් නමක් නොවේ. එය වෙනස් කළ නොහැකි දර්ශකයක් වන අතර එය ස්වයංක්රීයව භාවිතය මත යොමු වේ. මූලික වශයෙන් එය පහතට තල්ලු වේ:
int& j = i;
එය අභ්යන්තරව බවට පත්වේ
int* const j = &i;
const
දර්ශකයක් ක්රියාත්මක කිරීම සඳහා වලංගු ක්රමයකි . යොමු කිරීමක් සහ දර්ශකයක් අතර වෙනසක් ඇති බව එම නම්යශීලී බව ඔප්පු නොකරයි.
C ++ හි යොමු කිරීමක් යනු කුමක්ද? වස්තු වර්ගයක් නොවන වර්ගයේ නිශ්චිත අවස්ථාවක් .
C ++ හි දර්ශකය යනු කුමක්ද? වස්තු වර්ගයක් වන වර්ගයේ නිශ්චිත අවස්ථාවක් .
සිට වස්තුව වර්ගය ගත් ISO C ++ අර්ථ දැක්වීම :
ක වස්තුව වර්ගය අ (සමහරවිට වේ cv උත්සවයකට වර්ගය, සැඳහුම වර්ගය නොවේ නොවන බව -qualified) වර්ගය, හා නොවේ cv අඩුව.
දැන ගැනීම වැදගත් විය හැකිය, වස්තු වර්ගය යනු C ++ හි විශ්වයේ වර්ගයේ ඉහළ මට්ටමේ කාණ්ඩයකි. යොමු කිරීම ද ඉහළ මට්ටමේ කාණ්ඩයකි. නමුත් දර්ශකය එසේ නොවේ.
සංයෝග වර්ගයේ සන්දර්භය තුළ දර්ශකයන් සහ යොමු කිරීම් එකට සඳහන් වේ. මෙයට මූලික වශයෙන් හේතු වී ඇත්තේ (සහ දීර් extended කරන ලද) සී වෙතින් උරුම වූ ප්රකාශක සින්ටැක්ස් වල ස්වභාවයයි. (මීට අමතරව, එහි C ++ 11 සිට යොමු declarator එකකට වඩා වැඩි වගේ, සූචක තවමත් "unityped" වන අතර ඇත: &
+ &&
එදිරිව *
.) මෙම සන්දර්භය තුළ සී සමාන ශෛලිය සමග "දීර්ඝ" විසින් භාෂාවක් විශේෂිත කෙටුම්පත් තරමක් සාධාරණ වන්නේ ඒ නිසා . (මම තවමත් declarators අපද්රව්ය කාරක රීති ද සින්ටැක්ටික් expressiveness තර්ක ගොඩක් , මානව හා පරිශීලකයන් නිර්මාණයන් දෙකම දුෂ්කර කරයි. මේ අනුව, ඔවුන් සියලු කිරීමට සුදුසුකම් නැති බිල්ට්නව භාෂා සැලසුමකින්. මෙය PL නිර්මාණය පිළිබඳ සම්පූර්ණයෙන්ම වෙනස් මාතෘකාවකි.)
එසේ නොමැති නම්, එක් එක් යොමු කිරීම් සහිත නිශ්චිත වර්ගයක් ලෙස දර්ශකයන් සුදුසුකම් ලැබිය හැකි වීම වැදගත් නොවේ. ඒවා හුදෙක් සින්ටැක්ස් සමානතාවයට අමතරව පොදු ගුණාංග ඉතා ස්වල්පයක් බෙදා ගනී, එබැවින් බොහෝ අවස්ථාවන්හිදී ඒවා එකට දැමීමේ අවශ්යතාවයක් නොමැත.
ඉහත ප්රකාශ වල සඳහන් වන්නේ “දර්ශකයන්” සහ “යොමු කිරීම්” වර්ග ලෙස පමණි. ඒවායේ අවස්ථා (විචල්යයන් වැනි) ගැන උනන්දුවක් දක්වන ප්රශ්න කිහිපයක් තිබේ. බොහෝ වැරදි වැටහීම් ද ඇත.
ඉහළ මට්ටමේ කාණ්ඩවල වෙනස්කම් මගින් සෘජුවම දර්ශකයන් සමඟ බැඳී නොමැති බොහෝ කොන්ක්රීට් වෙනස්කම් දැනටමත් හෙළි කළ හැකිය:
cv
සුදුසුකම් තිබිය හැකිය. යොමු කිරීම් කළ නොහැක.යොමු කිරීම් පිළිබඳ තවත් විශේෂ නීති කිහිපයක්:
&&
පරාමිති පිළිබඳ විශේෂ රීති ("ඉදිරියට යැවීමේ යොමු කිරීම්" ලෙස) අච්චු පරාමිති අඩුකිරීමේදී බිඳ වැටීම මත පදනම්ව පරාමිතීන් "පරිපූර්ණ ඉදිරියට යැවීමට " ඉඩ දෙයි .std::initializer_list
ජීවිත කාලය දීර් extension කිරීමේ සමාන නීති කිහිපයක් අනුගමනය කරයි. එය තවත් පණුවන් කෑන් ය.යොමුව සින්ටැක්ටික් සීනි බව මම දනිමි, එබැවින් කේතය කියවීමට හා ලිවීමට පහසුය.
තාක්ෂණික වශයෙන්, මෙය සරල වැරදිය. යොමු කිරීම් C ++ හි ඇති වෙනත් කිසිදු අංගයක සින්ටැක්ටික් සීනි නොවේ, මන්දයත් ඒවා කිසිදු අර්ථකථන වෙනසක් නොමැතිව වෙනත් අංග මගින් හරියටම ප්රතිස්ථාපනය කළ නොහැකි බැවිනි.
(එලෙසින්ම, ලැම්ඩා-ප්රකාශනය වහන්සේගේ නොවන C ++ වෙනත් ඕනෑම ලක්ෂණ සින්ටැක්ටික් සීනි එය හරියටම සමාන "නම් නොකල" ගුණ ඇති යන්තරයෙනි නොහැකි නිසා අල්ලා ගනු විචල්ය ප්රකාශයට පත් පිණිස වැනි විචල්යතා ආරම්භය සඳහා විය හැකි බැවින්, වැදගත් විය හැකි, සැලකිය යුතු.)
C ++ සතුව ඇත්තේ මෙම දැඩි අර්ථයෙන් සින්ටැක්ටික් සීනි වර්ග කිහිපයක් පමණි. එක් උදාහරණයක් (C උරුම) එම බිල්ට් (-වුවමනාවන් නොවන) ක්රියාකරු වේ []
කරන, හරියටම බිල්ට් ක්රියාකරු ඒකජ කට එකතුවක් විශේෂිත ආකාරයේ එකම අර්ථ විචාර ලක්ෂණ සහිත අර්ථ *
හා ද්විමය+
.
ඉතින්, දර්ශකයක් සහ යොමු කිරීමක් යන දෙකම එකම මතක ප්රමාණයක් භාවිතා කරයි.
ඉහත ප්රකාශය වැරදිය. එවැනි වැරදි වැටහීම් වලක්වා ගැනීම සඳහා, ඒ වෙනුවට ISO C ++ නීති දෙස බලන්න:
සිට [intro.object] / 1 :
... වස්තුවක් එහි ඉදිකිරීම් කාලය තුළ, එහි ජීවිත කාලය පුරාම සහ විනාශයේ කාල පරිච්ඡේදයේදී ගබඩා කලාපයක් අල්ලා ගනී. ...
සිට [dcl.ref] / 4 :
යොමු කිරීමකට ගබඩා කිරීම අවශ්යද නැද්ද යන්න නිශ්චිතව දක්වා නැත.
මේවා අර්ථකථන ගුණාංග බව සලකන්න .
භාෂා සැලසුමේ අර්ථයෙන් යොමු දැක්වීම් සමඟ සම්බන්ධ කිරීමට තරම් සුදුසුකම් නොමැති වුවද, වෙනත් සන්දර්භයන් තුළ ඒවා අතර තේරීමක් කිරීම විවාදයට තුඩු දෙන තර්ක කිහිපයක් තවමත් පවතී, උදාහරණයක් ලෙස, පරාමිති වර්ග මත තේරීම් කරන විට.
නමුත් මෙය සම්පූර්ණ කතාව නොවේ. මම අදහස් කළේ, ඔබ සලකා බැලිය යුතු කරුණු හා යොමු කිරීම් වලට වඩා බොහෝ දේ ඇත.
ඔබට එවැනි විශේෂිත තේරීම් වලට ඇලී සිටීමට අවශ්ය නැතිනම්, බොහෝ අවස්ථාවන්හි පිළිතුර කෙටි ය: ඔබට දර්ශක භාවිතා කිරීමේ අවශ්යතාවයක් නැත, එබැවින් ඔබ එසේ නොකරයි . පොයින්ටර්ස් සාමාන්යයෙන් ප්රමාණවත් නොවන බැවින් ඒවා ඔබ අපේක්ෂා නොකරන බොහෝ දේ ඇඟවුම් කරන අතර ඒවා කේතයේ නඩත්තු කිරීමේ හැකියාව සහ (පවා) අතේ ගෙන යා හැකි හැකියාව අඩපණ කරන බොහෝ ව්යාජ උපකල්පන මත රඳා පවතී. අනවශ්ය ලෙස දර්ශකයන් මත යැපීම අනිවාර්යයෙන්ම නරක ශෛලියක් වන අතර එය නූතන සී ++ අර්ථයෙන් වැළකී සිටිය යුතුය. ඔබේ අරමුණ නැවත සලකා බලන්න, බොහෝ අවස්ථාවලදී අන්තිම වර්ගවල ලක්ෂණය වන්නේ දර්ශකය බව ඔබට වැටහෙනු ඇත .
&
1 වන පරාමිති වර්ගය ලෙස විශේෂිත cv - යොමු වර්ගය අවශ්ය වේ . (සාමාන්යයෙන් එය const
සුදුසුකම් ලැබිය යුතුය .)&&
යොමු වර්ගය අවශ්ය වේ . (සාමාන්යයෙන් සුදුසුකම් ලැබිය යුතු අය නොසිටිය යුතුය.)operator=
විශේෂ සාමාජික කාර්යයන් ලෙස අධික ලෙස පැටවීම සඳහා පිටපත් / චලන ඉදිකිරීම්කරුවන්ගේ 1 වන පරාමිතියට සමාන යොමු වර්ග අවශ්ය වේ.++
සඳහා ව්යාජ අවශ්ය වේ int
.unique_ptr
සහ shared_ptr
(හෝ වර්ණ සම්පන්නා විය අය සමඟ පවා ඔබ විසින් ඔබ විය ඔවුන් අවශ්ය නම් විනිවිද නොපෙනෙන ), ඒ වෙනුවට අමු සූචක වඩා.std::optional
, අමු දර්ශකයන්ට වඩා එතීම භාවිතා කරන්න .observer_ptr
පුස්තකාල මූලික ටීඑස් වැනි බොහෝ විට වඩාත් සුදුසු යමක් තිබේ.එකම ව්යතිරේකය වත්මන් භාෂාවෙන් ක්රියාත්මක කළ නොහැක:
operator new
. (කෙසේ වෙතත්, cv - void*
තවමත් බෙහෙවින් වෙනස් සහ ආරක්ෂිත සාමාන්ය වස්තුව සූචක සාපේක්ෂව ඔබ නොවන සමහර අනුකූල දීර්ඝ මත රඳා ඇති නම් හැරෙන්නට එය අනපේක්ෂිත පහිටුම් දක්වනය arithmetics සිදු පාලනය නිසා ය void*
GNU ගේ වගේ.)එබැවින්, ප්රායෝගිකව, පිළිතුර එතරම් පැහැදිලිය: සැකයක් ඇති විට, දර්ශකයන්ගෙන් වළකින්න . ඔබට දර්ශකයන් භාවිතා කළ යුත්තේ වෙනත් කිසිවක් වඩා සුදුසු නොවන බවට ඉතා පැහැදිලි හේතු ඇති විට පමණි. ඉහත සඳහන් කළ සුවිශේෂී අවස්ථා කිහිපයක් හැරුණු විට, එවැනි තේරීම් සෑම විටම පාහේ C ++ නොවේ - විශේෂිත (නමුත් බොහෝ විට භාෂාව ක්රියාත්මක කිරීම-විශේෂිත විය හැකිය). එවැනි අවස්ථා විය හැකිය:
ඔබ සමහර ගූගල් සෙවුම් ප්රති result ල හරහා ප්රශ්නය බැලීමට පැමිණියහොත් (C ++ සඳහා විශේෂිත නොවේ) , මෙය වැරදි ස්ථානයක් වීමට බොහෝ දුරට ඉඩ ඇත.
සී ++ හි යොමු කිරීම් තරමක් "අමුතු" ය, එය මූලික වශයෙන් පළමු පන්තිය නොවන බැවින්: ඒවා වස්තූන් හෝ යොමු කරනු ලබන කාර්යයන් ලෙස සලකනු ලැබේ, එබැවින් ඔවුන්ට පළමු පන්තියේ මෙහෙයුම් සඳහා සහාය වීමට අවස්ථාවක් නොලැබේ . සාමාජික ප්රවේශ ක්රියාකරු යොමු කරන ලද වස්තුවට ස්වාධීනව. වෙනත් භාෂාවන්ට ඔවුන්ගේ යොමු කිරීම් වලට සමාන සීමාවන් තිබිය හැකිය හෝ නොතිබිය හැකිය.
C ++ හි යොමු කිරීම් විවිධ භාෂාවන් හරහා අර්ථය ආරක්ෂා නොකරනු ඇත. නිදසුනක් ලෙස, පොදුවේ යොමු කිරීම් C ++ වැනි අගයන් මත අද්විතීය ගුණාංග අදහස් නොකෙරේ, එබැවින් එවැනි උපකල්පන වෙනත් භාෂාවලින් ක්රියා නොකරනු ඇත (තවද ඔබට ප්රති-නියැදි ඉතා පහසුවෙන් සොයාගත හැකිය, උදා: ජාවා, සී #, ...).
පොදුවේ විවිධ ක්රමලේඛන භාෂාවල යොමු කිරීම් අතර පොදු ගුණාංග කිහිපයක් තවමත් පැවතිය හැකිය, නමුත් SO හි වෙනත් ප්රශ්න සඳහා එය තබමු.
(පැති සටහනක්: ALGOL 68 එදිරිව පීඑල් / අයි වැනි ඕනෑම "සී-වැනි" භාෂාවන් සම්බන්ධ වීමට පෙර ප්රශ්නය වැදගත් විය හැකිය .)
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;
}
මට මේ කිසිවක් අවශ්ය නොවන්නේ නම් මම යොමු කිරීම් භාවිතා කරමි:
ශුන්ය දර්ශකයන් සෙන්ඩිනල් අගයක් ලෙස භාවිතා කළ හැකිය, බොහෝ විට ක්රියාකාරී බර පැටවීම හෝ බූල් භාවිතා කිරීම වළක්වා ගැනීම සඳහා ලාභ ක්රමයකි.
ඔබට දර්ශකයක් මත අංක ගණිතය කළ හැකිය. උදාහරණයක් වශයෙන්,p += offset;
&r + offset
ස්ථානය ඔබට ලිවිය හැකියr
කිසිවෙකු සඳහන් කර නැති මා දුටු දර්ශකයන් සහ යොමු කිරීම් අතර එක් මූලික වෙනසක් ඇත: යොමු තර්ක මඟින් ශ්රිත තර්ක වලදී පාස්-බයි-යොමු-අර්ථ නිරූපණයන් සක්රීය කරයි. දර්ශකයන්, එය මුලින් නොපෙනුනත්, නොපෙන්වයි: ඒවා ලබා දෙන්නේ වටිනාකමින් යුත් අර්ථකථන පමණි. මෙම ලිපියෙන් මෙය ඉතා සියුම් ලෙස විස්තර කර ඇත .
සුභ පැතුම්, & rzej
ව්යාකූලත්වයට එකතු වීමේ අවදානමක, මට යම් ආදානයක් දැමීමට අවශ්යයි, එය බොහෝ දුරට රඳා පවතින්නේ සම්පාදකයා යොමු කිරීම් ක්රියාත්මක කරන ආකාරය මත බව මට විශ්වාසයි, නමුත් 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 යක සඳහනක් හැරුණු විට, එය ඉදිකිරීම්කරු තුළ අර්ථ දැක්විය යුතුය, එය අඩංගු වස්තුවෙන් පසුව එය නිර්වචනය කිරීමට ප්රමාද වැඩියි).
මතක තබා ගන්න, ඉහත මගේ උදාහරණ පමණක් වන අතර, යොමු දැක්වීමක් යනු කුමක්ද යන්න නිරූපණය කරන උදාහරණ, ඔබට කිසි විටෙකත් ඒ ආකාරයෙන් යොමු කිරීමක් භාවිතා කිරීමට අවශ්ය නොවනු ඇත! යොමුව නිසි ලෙස භාවිතා කිරීම සඳහා දැනටමත් නියපොතු හිසට පහර දෙන පිළිතුරු ඕනෑ තරම් තිබේ
තවත් වෙනසක් නම්, ඔබට අවලංගු වර්ගයකට දර්ශක තිබිය හැකි අතර (එයින් අදහස් කරන්නේ ඕනෑම දෙයකට දර්ශකය) නමුත් අවලංගු කිරීම සඳහා යොමු කිරීම තහනම්ය.
int a;
void * p = &a; // ok
void & p = a; // forbidden
මෙම සුවිශේෂී වෙනස ගැන මම සැබවින්ම සතුටු වන බව පැවසිය නොහැක. ලිපිනයකින් ඕනෑම දෙයකට අර්ථය යොමු කිරීමත්, වෙනත් ආකාරයකින් යොමු කිරීම් සඳහා එකම හැසිරීමත් එයට ඉඩ දෙනු ඇතැයි මම කැමැත්තෙමි. යොමු කිරීම් භාවිතා කරමින් memcpy වැනි C පුස්තකාල ක්රියාකාරකම්වල සමානකම් නිර්වචනය කිරීමට එය ඉඩ දෙයි.
එසේම, ආදාන කර ඇති ශ්රිතයක පරාමිතියක් වන යොමු කිරීමක් දර්ශකයකට වඩා වෙනස් ලෙස හැසිරවිය හැක.
void increment(int *ptrint) { (*ptrint)++; }
void increment(int &refint) { refint++; }
void incptrtest()
{
int testptr=0;
increment(&testptr);
}
void increftest()
{
int testref=0;
increment(testref);
}
දර්ශක අනුවාදය ඇතුළත් කිරීමේදී බොහෝ සම්පාදකයින් ඇත්ත වශයෙන්ම මතකයට ලිවීමට බල කරනු ඇත (අපි ලිපිනය පැහැදිලිවම ගන්නෙමු). කෙසේ වෙතත්, ඔවුන් යොමු කිරීම වඩාත් ප්රශස්ත ලේඛනයක තබනු ඇත.
ඇත්ත වශයෙන්ම, දර්ශකය සහ යොමු කිරීම නොබැඳි ශ්රිත සඳහා එකම කේතයක් ජනනය කරන අතර, ශ්රිතය විසින් වෙනස් කර ආපසු ලබා නොදුනහොත්, යොමු දැක්වීමට වඩා සහජයෙන්ම අගය අනුව සම්මත කිරීම වඩා හොඳය.
පරිශීලකයන් විසින් නිර්වචනය කරන ලද වර්ගයක පෙරනිමි තර්කයක් සැපයීම තවත් යොමුකිරීමේ තවත් රසවත් භාවිතයකි:
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;
}
පෙරනිමි රසය යොමු කිරීම්වල 'තාවකාලික බැඳීමක් යොමු කිරීම' භාවිතා කරයි.
මෙම වැඩසටහන ප්රශ්නයේ පිළිතුර තේරුම් ගැනීමට උපකාරී වේ. මෙය "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
මෙහි ආවරණය නොවූ තවත් කරුණක් ඇති බව මට හැඟේ.
දර්ශකයන් මෙන් නොව, යොමු කිරීම් ඔවුන් යොමු කරන වස්තුවට කෘතීමව සමාන වේ , එනම් වස්තුවකට යෙදිය හැකි ඕනෑම මෙහෙයුමක් යොමු කිරීමක් සඳහා ක්රියා කරයි, සහ හරියටම එකම වාක්ය ඛණ්ඩය සමඟ (ව්යතිරේකය ඇත්ත වශයෙන්ම ආරම්භය වේ).
මෙය මතුපිටින් පෙනෙන්නට තිබුණද, 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 ++ සහ සම්මත පුස්තකාලයේ සැලකිය යුතු කොටසක් බලගන්වයි, එබැවින් මෙය යොමු කිරීම්වල ප්රධාන දේපලකි.
සමහර විට සමහර රූපක උපකාරී වනු ඇත; ඔබගේ ඩෙස්ක්ටොප් තිර අවකාශයේ සන්දර්භය තුළ -
දර්ශකයන් සහ යොමු කිරීම් අතර ඉතා වැදගත් තාක්ෂණික නොවන වෙනසක් ඇත: ශ්රිතයක් වෙත යොමු කරන ලද තර්කයක්, නියත නොවන යොමු කිරීමකින් ශ්රිතයකට සම්මත කරන ලද තර්කයකට වඩා දෘශ්යමාන වේ. උදාහරණයක් වශයෙන්:
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()
ඉහත සඳහන් පරිදි ක්රියාකාරී අත්සන් වලට ඉඩ නොදිය යුතු යැයි එම පුද්ගලයින් තර්ක කරති . ගූගල් හි සී ++ විලාසිතාවේ මාර්ගෝපදේශ මේ සඳහා උදාහරණයකි.
දර්ශකයක් 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 "="
const int& i = 0
.
වෙනස වන්නේ ක්රමලේඛ ක්රියාත්මක කිරීමේදී යම් වේලාවක නියත නොවන දර්ශක විචල්යය (නියතයට දර්ශකයක් සමඟ පටලවා නොගත යුතුය) වෙනස් කළ හැකි අතර, දර්ශක අර්ථ නිරූපණයන් භාවිතා කිරීම අවශ්ය වේ (&, *) ක්රියාකරුවන් වන අතර ආරම්භයේදී යොමු කිරීම් සැකසිය හැකිය. පමණක් (ඔබට ඒවා ඉදිකිරීම් ආරම්භක ලැයිස්තුවේ පමණක් සැකසිය හැකිය, නමුත් වෙනත් ආකාරයකින් නොවේ) සහ අර්ථ නිරූපණයට ප්රවේශ වන සාමාන්ය අගය භාවිතා කරන්න. මම ඉතා පැරණි පොතක කියවා ඇති පරිදි ක්රියාකරුවන් අධික ලෙස පැටවීම සඳහා සහය දැක්වීම සඳහා මූලික වශයෙන් යොමු කිරීම් හඳුන්වා දෙන ලදී. මෙම ත්රෙඩ් එකේ කවුරුහරි ප්රකාශ කර ඇති පරිදි - දර්ශකය 0 හෝ ඔබට අවශ්ය ඕනෑම අගයකට සැකසිය හැකිය. 0 (NULL, nullptr) යන්නෙන් අදහස් කරන්නේ දර්ශකය කිසිවක් නොමැතිව ආරම්භ කර ඇති බවයි. ශුන්ය දර්ශකය විරූපණය කිරීම දෝෂයකි. නමුත් ඇත්ත වශයෙන්ම දර්ශකයේ යම් නිවැරදි මතක ස්ථානයකට යොමු නොවන අගයක් අඩංගු විය හැකිය. ඔබ සැමවිටම නිවැරදි වර්ගයේ අගයක් ලබා දෙන හෙයින්, යොමු කළ නොහැකි දෙයකට යොමු කිරීමක් ආරම්භ කිරීමට පරිශීලකයාට ඉඩ නොදීමට ඔවුන්ගේ වාර්තා උත්සාහ කරයි. යොමු විචල්යය වැරදි මතක ස්ථානයකට ගෙන ඒමට බොහෝ ක්රම තිබුණත් - මෙය ගැඹුරින් හාරා නොගැනීම හොඳය. යන්ත්ර මට්ටමින් දර්ශකය සහ යොමු දෙකම එකසේ ක්රියාත්මක වේ - දර්ශකයන් හරහා. අත්යවශ්ය යොමුවලින් කියමු සින්ටැක්ටික් සීනි. rvalue යොමු කිරීම් මෙයට වෙනස් වේ - ඒවා ස්වාභාවිකවම සිරස් / ගොඩවල් වස්තු වේ. යොමු විචල්යය වැරදි මතක ස්ථානයකට ගෙන ඒමට බොහෝ ක්රම තිබුණත් - මෙය ගැඹුරින් හාරා නොගැනීම හොඳය. යන්ත්ර මට්ටමින් දර්ශකය සහ යොමු දෙකම එකසේ ක්රියාත්මක වේ - දර්ශකයන් හරහා. අත්යවශ්ය යොමුවලින් කියමු සින්ටැක්ටික් සීනි. rvalue යොමු කිරීම් මෙයට වෙනස් වේ - ඒවා ස්වාභාවිකවම සිරස් / ගොඩවල් වස්තු වේ. යොමු විචල්යය වැරදි මතක ස්ථානයකට ගෙන ඒමට බොහෝ ක්රම තිබුණත් - මෙය ගැඹුරින් හාරා නොගැනීම හොඳය. යන්ත්ර මට්ටමින් දර්ශකය සහ යොමු දෙකම එකසේ ක්රියාත්මක වේ - දර්ශකයන් හරහා. අත්යවශ්ය යොමුවලින් කියමු සින්ටැක්ටික් සීනි. rvalue යොමු කිරීම් මෙයට වෙනස් වේ - ඒවා ස්වාභාවිකවම සිරස් / ගොඩවල් වස්තු වේ.
සරල වචන වලින් කිවහොත්, අපට යොමු දැක්වීමක් විචල්යයක විකල්ප නමක් වන අතර, දර්ශකය යනු වෙනත් විචල්යයක ලිපිනය රඳවා ගන්නා විචල්යයකි. උදා
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 */