කේතීකරණ විලාසය අවසානයේ ආත්මීය වන අතර සැලකිය යුතු කාර්යසාධන ප්රතිලාභ එයින් ලැබෙනු ඇතැයි සිතිය නොහැකිය. ඒකාකාරී ආරම්භය ලිබරල් භාවිතයෙන් ඔබ ලබා ගන්නා බව මම කියන්නේ මෙන්න:
අතිරික්ත යතුරු නාම අවම කරයි
පහත සඳහන් කරුණු සලකා බලන්න:
vec3 GetValue()
{
return vec3(x, y, z);
}
මට vec3
දෙවරක් ටයිප් කිරීමට අවශ්ය ඇයි ? ඒ සඳහා කාරණයක් තිබේද? සම්පාදකයා හොඳ සහ හොඳින් දන්නා අතර ශ්රිතය නැවත පැමිණේ. "මෙම අගයන් සමඟ මා ආපසු එන දෙයෙහි ඉදිකිරීම්කරු අමතා එය ආපසු ලබා දෙන්න" යැයි මට කිව නොහැක්කේ ඇයි? ඒකාකාර ආරම්භයක් සමඟ, මට පුළුවන්:
vec3 GetValue()
{
return {x, y, z};
}
සෑම දෙයක්ම ක්රියා කරයි.
ඊටත් වඩා හොඳ වන්නේ ශ්රිත තර්ක සඳහා ය. මෙය සලකා බලන්න:
void DoSomething(const std::string &str);
DoSomething("A string.");
ටයිප් std::string
නාමයක් ටයිප් නොකර එය ක්රියා කරයි, මන්දයත් const char*
ව්යංගයෙන් එය ගොඩනගන්නේ කෙසේදැයි දන්නා බැවිනි . එය අනර්ඝයි. නමුත් එම නූල පැමිණියේ නම්, RapidXML කියන්න. නැත්නම් ලුවා නූලක්. එනම්, මම කියමු, මම ඇත්ත වශයෙන්ම ඉදිරියෙන් ඇති නූල් වල දිග දනිමි. මෙම std::string
ඉතා ගත වන බව ඉදිකිරීමටත් const char*
මම යන්තම් සමත් නම් වැල දිග ගන්න වෙනවා const char*
.
පැහැදිලිවම දිගක් ගතවන අධි බරක් ඇත. නමුත් එය භාවිතා කිරීමට, මට මෙය කිරීමට සිදුවේ : DoSomething(std::string(strValue, strLen))
. අමතර ටයිප් නාමය එහි ඇත්තේ ඇයි? වර්ගය කුමක්දැයි සම්පාදකයා දනී. මෙන් auto
, අපට අමතර ටයිප් නාම තිබීම වළක්වා ගත හැකිය:
DoSomething({strValue, strLen});
එය ක්රියාත්මක වේ. යතුරු ලියන නැත, කරදරයක් නැත, කිසිවක් නැත. සම්පාදකයා සිය කාර්යය ඉටු කරයි, කේතය කෙටි වන අතර සෑම කෙනෙකුම සතුටු වේ.
පළමු අනුවාදය ( DoSomething(std::string(strValue, strLen))
) වඩා පැහැදිලිව පෙනෙන බවට තර්ක කළ යුතු බව පිළිගත යුතුය . එනම්, සිදුවන්නේ කුමක්ද සහ කවුරුන් කරන්නේ කුමක්ද යන්න පැහැදිලිය. එය යම් තාක් දුරට සත්යයකි; ඒකාකාර ආරම්භක-පදනම් වූ කේතය අවබෝධ කර ගැනීම සඳහා ශ්රිත මූලාකෘතිය බැලීම අවශ්ය වේ. නියත නොවන යොමු කිරීමකින් ඔබ කිසි විටෙකත් පරාමිතීන් සම්මත නොකළ යුතු යැයි සමහරු පැවසීමට එකම හේතුව මෙයයි: එවිට වටිනාකමක් වෙනස් කරන්නේ නම් ඔබට ඇමතුම් අඩවියේ දැකිය හැකිය.
එහෙත් එය එසේ ම කිව හැකිය auto
; ඔබට ලැබෙන්නේ කුමක්ද යන්න දැන ගැනීම auto v = GetSomething();
සඳහා අර්ථ දැක්වීම බැලීම අවශ්ය වේ GetSomething
. නමුත් auto
ඔබට එයට පිවිසීමෙන් පසු නොසැලකිලිමත් ලෙස අතහැර දැමීම භාවිතා කිරීම නතර වී නැත . පුද්ගලිකව, මම හිතන්නේ ඔබ එය පුරුදු වූ පසු එය හොඳ වනු ඇත. විශේෂයෙන් හොඳ IDE සමඟ.
කිසි විටෙකත් වඩාත්ම කරදරකාරී විග්රහය ලබා නොගන්න
මෙන්න කේත කිහිපයක්.
class Bar;
void Func()
{
int foo(Bar());
}
පොප් ප්රශ්නාවලිය: කුමක්ද foo
? ඔබ "විචල්යයක්" ලෙස පිළිතුරු දුන්නේ නම්, ඔබ වැරදිය. එය ඇත්ත වශයෙන්ම ශ්රිතයක මූලාකෘතිය වන අතර එහි පරාමිතිය ලෙස ශ්රිතයක් නැවත ලබා දෙන ශ්රිතයක් වන Bar
අතර foo
ශ්රිතයේ ප්රතිලාභ අගය පූර්ණ වේ.
මෙය C ++ ගේ “වඩාත්ම කරදරකාරී විග්රහය” ලෙස හැඳින්වෙන්නේ එය මිනිසෙකුට කිසිසේත්ම තේරුමක් නැති බැවිනි. නමුත් C ++ හි නීති රීති වලට මෙය අවශ්ය වේ: එය ක්රියාකාරී මූලාකෘතියක් ලෙස අර්ථ දැක්විය හැකි නම් එය එසේ වනු ඇත. ගැටලුව වන්නේ Bar()
; එය කාරණා දෙකෙන් එකක් විය හැකිය. එය නම් කරන ලද වර්ගයක් විය හැකිය Bar
, එයින් අදහස් කරන්නේ එය තාවකාලික එකක් නිර්මාණය කරන බවයි. නැතහොත් එය පරාමිතීන් නොගෙන ආපසු ලබා දෙන ශ්රිතයක් විය හැකිය Bar
.
ඒකාකාර ආරම්භය ශ්රිත මූලාකෘතියක් ලෙස අර්ථ දැක්විය නොහැක:
class Bar;
void Func()
{
int foo{Bar{}};
}
Bar{}
සෑම විටම තාවකාලික නිර්මාණය කරයි. int foo{...}
සෑම විටම විචල්යයක් නිර්මාණය කරයි.
ඔබට භාවිතා කිරීමට අවශ්ය අවස්ථා බොහෝමයක් ඇත, Typename()
නමුත් C ++ හි විග්රහ කිරීමේ නීති නිසා එය කළ නොහැක. සමග Typename{}
, අවිනිශ්චිතතාවයක් නොමැත.
එසේ නොකිරීමට හේතු
ඔබ අත්හරින එකම සැබෑ බලය පටු වීමයි. ඒකාකාර ආරම්භයක් සහිත විශාල අගයක් සමඟ ඔබට කුඩා අගයක් ආරම්භ කළ නොහැක.
int val{5.2};
එය සම්පාදනය නොකරනු ඇත. ඔබට එය පැරණි තාලයේ ආරම්භයකින් කළ හැකි නමුත් ඒකාකාරී ආරම්භයක් නොවේ.
ආරම්භක ලැයිස්තු සැබවින්ම ක්රියාත්මක කිරීම සඳහා මෙය අර්ධ වශයෙන් සිදු කරන ලදී. එසේ නොවුවහොත්, ආරම්භක ලැයිස්තු වර්ග සම්බන්ධයෙන් නොපැහැදිලි අවස්ථා රාශියක් ඇත.
ඇත්ත වශයෙන්ම, ඇතැම් එවැනි කේතය කියා සමහර අය තර්ක කරනවා , ජාතිය සම්පාදනය වී නැත. මම පෞද්ගලිකව එකඟ වෙමි; පටු වීම ඉතා භයානක වන අතර එය අප්රසන්න හැසිරීමට හේතු වේ. සම්පාදක අවධියේදී එම ගැටළු ඉක්මනින් අල්ලා ගැනීම වඩාත් සුදුසුය. අවම වශයෙන්, පටු වීම මඟින් යමෙකු කේතය ගැන එතරම් නොසිතන බව අඟවයි.
ඔබේ අනතුරු ඇඟවීමේ මට්ටම ඉහළ මට්ටමක පවතී නම් සම්පාදකයින් සාමාන්යයෙන් මෙවැනි දේ ගැන ඔබට අනතුරු අඟවන බව සැලකිල්ලට ගන්න. ඉතින් ඇත්ත වශයෙන්ම, මේ සියල්ල කරන්නේ අනතුරු ඇඟවීම බලාත්මක දෝෂයක් බවට පත් කිරීමයි. ඔබ කෙසේ හෝ එය කළ යුතු යැයි සමහරු කියනු ඇත;)
එසේ නොකිරීමට තවත් එක් හේතුවක් තිබේ:
std::vector<int> v{100};
මෙය කරන්නේ කුමක්ද? vector<int>
පෙරනිමියෙන් සාදන ලද අයිතම සියයක් සමඟ එය නිර්මාණය කළ හැකිය . නැතහොත් එහි vector<int>
වටිනාකම 1 අයිතමයක් සමඟ නිර්මාණය කළ හැකිය 100
. දෙකම න්යායාත්මකව හැකි ය.
ඇත්ත වශයෙන්ම, එය දෙවැන්න කරයි.
මන්ද? ආරම්භක ලැයිස්තු ඒකාකාරී ආරම්භයට සමාන සින්ටැක්ස් භාවිතා කරයි. එබැවින් අපැහැදිලි අවස්ථාවකදී කුමක් කළ යුතුද යන්න පැහැදිලි කිරීමට නීති කිහිපයක් තිබිය යුතුය. රීතිය ඉතා සරල ය: සම්පාදකයාට වරහන්-ආරම්භක ලැයිස්තුවක් සහිත ආරම්භක ලැයිස්තු ඉදිකිරීම්කරුවෙකු භාවිතා කළ හැකි නම් , එසේ වනු ඇත . සිට vector<int>
ගනී බව initializer ලැයිස්තුව ඉදිකිරීමටත් ඇත initializer_list<int>
, සහ {100} වලංගු විය හැකි initializer_list<int>
, එම නිසා එය විය යුතුය .
ප්රමාණයේ ඉදිකිරීම්කරු ලබා ගැනීම සඳහා, ඔබ ()
ඒ වෙනුවට භාවිතා කළ යුතුය {}
.
vector
මෙය පූර්ණ සංඛ්යාවක් බවට පරිවර්තනය කළ නොහැකි දෙයක් නම් මෙය සිදු නොවන බව සලකන්න . ආරම්භක_ ලැයිස්තුවක් එම vector
වර්ගයේ ආරම්භක ලැයිස්තු සාදන්නාට නොගැලපේ , එබැවින් සම්පාදකයාට අනෙක් ඉදිකිරීම්කරුවන්ගෙන් තෝරා ගැනීමට නිදහස ඇත.