ක්‍රියාකරු අධික ලෙස පැටවීම සඳහා වන මූලික නීති සහ මුග්ධ මොනවාද?


2152

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

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


64
අපි C ++ - FAQ ටැගය සමඟ ඉදිරියට යාමට යන්නේ නම්, ප්‍රවේශයන් සංයුති කළ යුතු ආකාරය මෙයයි.
ජෝන් ඩිබ්ලිං

ක්‍රියාකරු අධි බර පැටවීම පිළිබඳව මම ජර්මානු සී ++ ප්‍රජාව සඳහා කෙටි ලිපි මාලාවක් ලියා ඇත: 1 වන කොටස: සී ++ හි ක්‍රියාකරු අධි බර පැටවීම අර්ථ නිරූපණයන්, සාමාන්‍ය භාවිතය සහ සියලුම ක්‍රියාකරුවන් සඳහා විශේෂතා ආවරණය කරයි. මෙහි ඔබගේ පිළිතුරු සමඟ අතිච්ඡාදනයන් ඇත, කෙසේ වෙතත් අමතර තොරතුරු කිහිපයක් තිබේ. 2 සහ 3 කොටස් Boost.Operators භාවිතා කිරීම සඳහා නිබන්ධනයක් සාදයි. මම ඒවා පරිවර්තනය කර පිළිතුරු ලෙස එකතු කිරීමට ඔබ කැමතිද?
ආර්න් මර්ට්ස්

ඔහ්, සහ ඉංග්‍රීසි පරිවර්තනයක් ද ඇත: මූලික කරුණු සහ පොදු භාවිතයන්
ආර්න් මර්ට්ස්

Answers:


1047

අධි බර පැටවීමට පොදු ක්‍රියාකරුවන්

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

පැවරුම් ක්‍රියාකරු

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

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

Bitshift Operators (ධාරාව I / O සඳහා භාවිතා කරයි)

බිට්ෂිෆ්ට් ක්‍රියාකරුවන් <<සහ >>, සී වෙතින් උරුම වන බිට්-හැසිරවීමේ කාර්යයන් සඳහා දෘඩාංග අතුරුමුහුණත් සඳහා තවමත් භාවිතා කර ඇතත්, බොහෝ යෙදුම්වල අධික ලෙස පටවන ලද ධාරා ආදානය සහ ප්‍රතිදාන ක්‍රියාකරුවන් ලෙස වඩාත් ප්‍රචලිත වී ඇත. බිටු-හැසිරවීමේ ක්‍රියාකරුවන් ලෙස මඟ පෙන්වීම අධික ලෙස පැටවීම සඳහා, ද්විමය අංක ගණිත ක්‍රියාකරුවන්ගේ පහත කොටස බලන්න. ඔබේ වස්තුව අයෝස්ට්රීම් සමඟ භාවිතා කරන විට ඔබේ අභිරුචි ආකෘතිය ක්රියාත්මක කිරීම සහ තර්කනය විග්‍රහ කිරීම සඳහා, දිගටම කරගෙන යන්න.

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

std::ostream& operator<<(std::ostream& os, const T& obj)
{
  // write obj to stream

  return os;
}

std::istream& operator>>(std::istream& is, T& obj)
{
  // read obj from stream

  if( /* no valid object of T found in stream */ )
    is.setstate(std::ios::failbit);

  return is;
}

ක්‍රියාත්මක කිරීමේදී operator>>, ප්‍රවාහයේ තත්වය අතින් සැකසීම අවශ්‍ය වන්නේ කියවීම සාර්ථක වූ විට පමණි, නමුත් ප්‍රති result ලය බලාපොරොත්තු වන දෙය නොවේ.

ක්‍රියාකාරී ඇමතුම් ක්‍රියාකරු

ශ්‍රිත වස්තු නිර්මාණය කිරීම සඳහා භාවිතා කරන ශ්‍රිත ඇමතුම් ක්‍රියාකරු, ෆන්ක්ටර්ස් ලෙසද හැඳින්වේ, එය සාමාජික ශ්‍රිතයක් ලෙස අර්ථ දැක්විය යුතුය , එබැවින් එය සැමවිටම thisසාමාජික ශ්‍රිතයන්ගේ ව්‍යංග තර්කය ඇත. මේ හැරුණු විට, ශුන්‍යය ඇතුළුව ඕනෑම අමතර තර්ක ගණනාවක් ගැනීමට එය අධික ලෙස පැටවිය හැකිය.

සින්ටැක්ස් සඳහා උදාහරණයක් මෙන්න:

class foo {
public:
    // Overloaded call operator
    int operator()(const std::string& y) {
        // ...
    }
};

භාවිතය:

foo f;
int a = f("hello");

C ++ සම්මත පුස්තකාලය පුරා, ක්‍රියාකාරී වස්තු සෑම විටම පිටපත් කරනු ලැබේ. එබැවින් ඔබේම ක්‍රියාකාරී වස්තු පිටපත් කිරීමට ලාභදායී විය යුතුය. ශ්‍රිත වස්තුවකට පිටපත් කිරීම සඳහා මිල අධික දත්ත භාවිතා කිරීමට අවශ්‍ය නම්, එම දත්ත වෙනත් තැනක ගබඩා කර තැබීම වඩා හොඳය.

සංසන්දනය කරන්නන්

ද්විමය infix සංසන්දනය ක්රියාකරුවන්, අතේ මාපට ඇඟිල්ල නීති රීති අනුව, සාමාජික නොවන කාර්යයන් ලෙස ක්රියාත්මක කළ යුතු 1 . ඒකීය උපසර්ගය ප්‍රතික්ෂේප කිරීම !(එකම නීතිරීතිවලට අනුව) සාමාජික ශ්‍රිතයක් ලෙස ක්‍රියාත්මක කළ යුතුය. (නමුත් සාමාන්‍යයෙන් එය අධික ලෙස පැටවීම හොඳ අදහසක් නොවේ.)

සම්මත පුස්තකාලයේ ඇල්ගොරිතම (උදා std::sort()) සහ වර්ග (උදා std::map) සැමවිටම පවතිනු ඇතැයි අපේක්ෂා operator<කරයි. කෙසේ වෙතත්, ඔබේ වර්ගයේ පරිශීලකයින් අනෙක් සියලුම ක්‍රියාකරුවන් ද පැමිණෙනු ඇතැයි අපේක්ෂා කරනු ඇත , එබැවින් ඔබ නිර්වචනය කරන්නේ නම් operator<, ක්‍රියාකරු අධි බර පැටවීමේ තුන්වන මූලික රීතිය අනුගමනය කිරීමට වග බලා ගන්න සහ අනෙක් සියලුම බූලියන් සංසන්දනාත්මක ක්‍රියාකරුවන් නිර්වචනය කරන්න. ඒවා ක්‍රියාත්මක කිරීමට කැනොනිකල් ක්‍රමය මෙයයි:

inline bool operator==(const X& lhs, const X& rhs){ /* do actual comparison */ }
inline bool operator!=(const X& lhs, const X& rhs){return !operator==(lhs,rhs);}
inline bool operator< (const X& lhs, const X& rhs){ /* do actual comparison */ }
inline bool operator> (const X& lhs, const X& rhs){return  operator< (rhs,lhs);}
inline bool operator<=(const X& lhs, const X& rhs){return !operator> (lhs,rhs);}
inline bool operator>=(const X& lhs, const X& rhs){return !operator< (lhs,rhs);}

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

ඉතිරි ද්විමය බූලියන් ක්‍රියාකරුවන් ( ||, &&) අධික ලෙස පැටවීම සඳහා වන වාක්‍ය ඛණ්ඩය සංසන්දනාත්මක ක්‍රියාකරුවන්ගේ නීති රීති අනුගමනය කරයි. කෙසේ වෙතත්, එය ඉතා ඔබ මේ සඳහා සාධාරණ භාවිතය නඩුව සොයා බව නොහැක්කකි 2 .

1 මාපට ඇඟිල්ලේ සියලු නීති මෙන්ම, සමහර විට මෙය බිඳ දැමීමටද හේතු තිබිය හැක. එසේ නම්, සාමාජික සඳහා කටයුතු වනු ඇත, ද්විමය සංසන්දනය ක්රියාකරුවන් වම් අත යන අගයද බව අමතක කරන්න එපා *this, විය යුතු constද,. එබැවින් සාමාජික ශ්‍රිතයක් ලෙස ක්‍රියාත්මක කරන සංසන්දනාත්මක ක්‍රියාකරුවෙකුට මෙම අත්සන තිබිය යුතුය:

bool operator<(const X& rhs) const { /* do actual comparison with *this */ }

( constඅවසානයේ සටහන් කරන්න.)

2 කෙටිමං අර්ථකථනවල සාදන ලද අනුවාදය ||සහ &&භාවිතා කරන බව සැලකිල්ලට ගත යුතුය . පරිශීලකයා අර්ථ දක්වා ඇති ඒවා (ඒවා ක්‍රම ඇමතුම් සඳහා සින්ටැක්ටික් සීනි බැවින්) කෙටිමං අර්ථකථන භාවිතා නොකරයි. පරිශීලකයා මෙම ක්‍රියාකරුවන්ට කෙටිමං අර්ථකථන ලබා දෙනු ඇතැයි අපේක්ෂා කරන අතර ඔවුන්ගේ කේතය එය මත රඳා පවතී, එබැවින් ඒවා නිර්වචනය කිරීමට කිසි විටෙකත් උපදෙස් දෙනු නොලැබේ.

අංක ගණිත ක්‍රියාකරුවන්

ඒකීය ගණිත ක්‍රියාකරුවන්

ඒකීය වර්ධක හා අඩුවීමේ ක්‍රියාකරුවන් උපසර්ගය සහ පසු සැකසුම් රසය යන දෙකෙන්ම පැමිණේ. එකක් අනෙකාට පැවසීමට නම්, පෝස්ට්ෆික්ස් ප්‍රභේද අතිරේක ව්‍යාජ int තර්කයක් ගනී. ඔබ වැඩිපුර පැටවීම හෝ අඩුවීම නම්, සෑම විටම උපසර්ගය සහ පෝස්ට්ෆික්ස් අනුවාද දෙකම ක්‍රියාත්මක කිරීමට වග බලා ගන්න. වර්ධකයේ කැනොනිකල් ක්‍රියාත්මක කිරීම මෙන්න, අඩුවීම එකම නීති අනුගමනය කරයි:

class X {
  X& operator++()
  {
    // do actual increment
    return *this;
  }
  X operator++(int)
  {
    X tmp(*this);
    operator++();
    return tmp;
  }
};

පෝස්ට්ෆික්ස් ප්‍රභේදය උපසර්ගය අනුව ක්‍රියාත්මක වන බව සලකන්න. පෝස්ට්ෆික්ස් අතිරේක පිටපතක් කරන බව සලකන්න. 2

ඒකීය us ණ සහ ප්ලස් අධික ලෙස පැටවීම එතරම් සුලභ නොවන අතර බොහෝ විට වළක්වා ගත හැකිය. අවශ්‍ය නම්, ඒවා බොහෝ විට සාමාජික කාර්යයන් ලෙස පැටවිය යුතුය.

2 තවද, postfix ප්රභේද්යයක් වැඩි වැඩ කරන්නේ බව කරුණාවෙන් හා ඒ නිසා අඩු කාර්යක්ෂම භාවිතා කිරීමේ උපසර්ගය ප්රභේද්යයක් වඩා. සාමාන්‍යයෙන් පෝස්ට්ෆික්ස් වර්ධකයට වඩා උපසර්ග වර්ධක වලට වැඩි කැමැත්තක් දැක්වීමට මෙය හොඳ හේතුවකි. සම්පාදකයින්ට සාමාන්‍යයෙන් බිල්ට් වර්ග සඳහා පෝස්ට්ෆික්ස් වර්ධකයේ අමතර කාර්යයන් ප්‍රශස්තිකරණය කළ හැකි නමුත්, පරිශීලක අර්ථ දක්වන ලද වර්ග සඳහා ඔවුන්ට එයම කළ නොහැකි වනු ඇත (එය ලැයිස්තු අනුකාරකයක් ලෙස අහිංසක ලෙස පෙනෙන දෙයක් විය හැකිය). ඔබ පුරුදු වූ පසු i++, ගොඩනංවන ලද වර්ගයක් නොමැති ++iවිට ඒ වෙනුවට මතක තබා ගැනීම ඉතා අපහසු වේ i(ප්ලස් වර්ගයක් වෙනස් කිරීමේදී ඔබට කේතය වෙනස් කළ යුතුය), එබැවින් සෑම විටම පුරුද්දක් කර ගැනීම වඩා හොඳය. පෝස්ට්ෆික්ස් පැහැදිලිවම අවශ්‍ය නොවන්නේ නම් උපසර්ග වර්ධක භාවිතා කිරීම.

ද්විමය අංක ගණිත ක්‍රියාකරුවන්

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

අපගේ නියමානුකූල නියමයන්ට අනුව, +සහ එහි සගයන් සාමාජිකයන් නොවන අතර ඔවුන්ගේ සංයුක්ත පැවරුම් සගයන් ( +=යනාදිය) ඔවුන්ගේ වම් තර්කය වෙනස් කරමින් සාමාජිකයෙකු විය යුතුය. +=සහ සඳහා ආදර්ශමත් කේතය මෙන්න +; අනෙක් ද්විමය ගණිත ක්‍රියාකරුවන් එකම ආකාරයකින් ක්‍රියාත්මක කළ යුතුය:

class X {
  X& operator+=(const X& rhs)
  {
    // actual addition of rhs to *this
    return *this;
  }
};
inline X operator+(X lhs, const X& rhs)
{
  lhs += rhs;
  return lhs;
}

operator+=එහි ප්‍රති result ලය යොමු operator+කිරීමකට ලබා දෙන අතර එහි ප්‍රති .ලයේ පිටපතක් ලබා දෙයි. ඇත්ත වශයෙන්ම, යොමු කිරීමක් ආපසු යැවීම සාමාන්‍යයෙන් පිටපතක් ආපසු ලබා දීමට වඩා කාර්යක්ෂම වේ, නමුත් එසේ නම් operator+, පිටපත් කිරීම සඳහා වෙනත් ක්‍රමයක් නොමැත. ඔබ ලියන විට a + b, ප්‍රති result ලය නව අගයක් වනු ඇතැයි ඔබ අපේක්ෂා කරයි, එබැවින් operator+නව අගයක් ආපසු ලබා දිය යුතුය. 3operator+ එහි වම් ක්‍රියාකාරිත්වය සංයුක්ත යොමු කිරීමකට වඩා පිටපතක් මගින් ගන්නා බව සලකන්න . මෙයට හේතුව operator=එහි පිටපතකට එහි තර්කය ගැනීමට හේතුවයි .

බිටු හැසිරවීමේ ක්‍රියාකරුවන් ~ & | ^ << >>ගණිතමය ක්‍රියාකරුවන් මෙන් ක්‍රියාත්මක කළ යුතුය. කෙසේ වෙතත්, (අධි බර පැටවීම <<සහ >>ප්‍රතිදානය සහ ආදානය හැර) මේවා අධික ලෙස පැටවීම සඳහා සාධාරණ භාවිත අවස්ථා ඉතා අල්පය.

3 නැවතත්, මෙම සිට ගත යුතු පාඩම වන්නේ a += bවඩා කාර්යක්ෂම, සාමාන්යයෙන්, ය a + bහැකි නම් කැමති විය යුතුය.

අරා දායකත්වය

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

class X {
        value_type& operator[](index_type idx);
  const value_type& operator[](index_type idx) const;
  // ...
};

ඔබේ පන්තියේ පරිශීලකයින්ට ආපසු ලබා දෙන දත්ත මූලද්‍රව්‍ය වෙනස් කිරීමට ඔබට අවශ්‍ය නොවන්නේ නම් operator[](ඔබට නොනවතින ප්‍රභේදය මඟ හැරිය හැක), ඔබ සැමවිටම ක්‍රියාකරුගේ ප්‍රභේද දෙකම ලබා දිය යුතුය.

Value_type යනු සාදන ලද වර්ගයකට යොමු වීමට දන්නා නම්, ක්‍රියාකරුගේ සංයුක්ත ප්‍රභේදය සංයුක්ත යොමු කිරීමක් වෙනුවට පිටපතක් ආපසු ලබා දිය යුතුය:

class X {
  value_type& operator[](index_type idx);
  value_type  operator[](index_type idx) const;
  // ...
};

පොයින්ටර් වැනි වර්ග සඳහා ක්‍රියාකරුවන්

ඔබේම අනුකාරක හෝ ස්මාර්ට් *පොයින්ටර්ස් නිර්වචනය කිරීම සඳහා, ඔබට ඒකීය උපසර්ග විරූපණ ක්‍රියාකරු සහ ද්විමය ඉන්ෆික්ස් පොයින්ටර් සාමාජික ප්‍රවේශ ක්‍රියාකරු අධික ලෙස පැටවිය යුතුය ->:

class my_ptr {
        value_type& operator*();
  const value_type& operator*() const;
        value_type* operator->();
  const value_type* operator->() const;
};

මේවාට ද සෑම විටම පාහේ const සහ non non const අනුවාදයක් අවශ්‍ය බව සලකන්න. සඳහා ->ක්රියාකරු, නම් value_typeවේ class(හෝ structහෝ unionවර්ගය), තවත් operator->()ඇත්තෙන් වෙනසට භාජනය, ක දක්වා හැඳින්වේ operator->()පන්තියේ නොවන වර්ගයේ අගය පැමිණේ.

ක්‍රියාකරුගේ අවිධිමත් ලිපිනය කිසි විටෙකත් අධික ලෙස පැටවිය යුතු නොවේ.

සඳහා operator->*()බලන්න මේ ප්රශ්නය . එය කලාතුරකින් භාවිතා වන අතර කලාතුරකින් අධික ලෙස පටවනු ලැබේ. ඇත්ත වශයෙන්ම, අනුකාරක පවා එය අධික ලෙස පටවන්නේ නැත.


පරිවර්තන ක්‍රියාකරුවන් වෙත දිගටම යන්න


89
operator->()ඇත්ත වශයෙන්ම අතිශයින්ම අමුතුයි. එය නැවත ලබා දීම අවශ්‍ය නොවේ value_type*- ඇත්ත වශයෙන්ම, එය වෙනත් පන්ති වර්ගයක් ආපසු ලබා දිය හැකිය, එම පන්තියේ වර්ගයට එය තිබේ නම්operator->() එය පසුව කැඳවනු ලැබේ. නැවත පැමිණීමේ වර්ගයක් සිදුවන operator->()තුරු මෙම පුනරාවර්තන ඇමතුම් ඉදිරියට යයි value_type*. පිස්සුව! :)
j_random_hacker

2
එය හරියටම .ලදායීතාවය ගැන නොවේ. සාම්ප්‍රදායික-මුග්ධ ආකාරයකින් අපට එය අවස්ථා කිහිපයකින් කළ නොහැකි ය: මෙහෙයුම් දෙකෙහිම අර්ථ දැක්වීම නොවෙනස්ව පැවතිය යුතු විට අපි ප්‍රති .ලය ගණනය කරමු. මා පැවසූ පරිදි, සම්භාව්‍ය උදාහරණ දෙකක් ඇත: matrices ගුණ කිරීම සහ බහුපද ගුණ කිරීම. අපි නිර්වචනය විය *අනුව *=නමුත් පළමු මෙහෙයුමේ එක් නිසා එය අමුතු වනු *=නොකරමි හැටිත් නව වස්තුව, ප්රතිඵලය නිර්මාණය කරන්න. For-ijk loop එකෙන් පසුව, අපි මෙම තාවකාලික වස්තුව සමඟ හුවමාරු කර ගනිමු *this. එනම්. 1.copy, 2.operator *, 3.swap
Luc Hermitte

6
ඔබගේ දර්ශකයට සමාන ක්‍රියාකරුවන්ගේ සංයුක්ත / නොනවතින අනුවාදයන් සමඟ මම එකඟ නොවෙමි, උදා: `const value_type & operator * () const;` - මෙය T* constනැවත නැවත යොමු කිරීමක් සිදු කිරීමක් වැනිය const T&, එය එසේ නොවේ. නැතහොත් වෙනත් වචන වලින් කිවහොත්: කොන්ස්ට් පොයින්ටරයක් ​​මගින් කොන්ස්ට් පොයින්ටියක් අදහස් නොකෙරේ. ඇත්ත වශයෙන්ම, එය අනුකරණය කිරීම සුළුපටු නොවේ T const *- const_iteratorසම්මත පුස්තකාලයේ ඇති සමස්ත දේවල් සඳහා හේතුව එයයි . නිගමනය: අත්සන විය යුතුයreference_type operator*() const; pointer_type operator->() const
ආර්න් මර්ට්ස්

6
එක් අදහස් දැක්වීමක්: යෝජනා කරන ලද ද්විමය ගණිත ක්‍රියාකරුවන් ක්‍රියාත්මක කිරීම එතරම් කාර්යක්ෂම නොවේ. සේ බූස්ට් ක්‍රියාකරුවන්ගේ ශීර්ෂක සමමිතික සටහන: boost.org/doc/libs/1_54_0/libs/utility/operators.htm#symmetry ඔබ පළමු පරාමිතියේ දේශීය පිටපතක් භාවිතා කරන්නේ නම් තවත් එක් පිටපතක් වළක්වා ගත හැකිය, කරන්න + =, සහ ආපසු එවන්න දේශීය පිටපත. මෙය NRVO ප්‍රශස්තිකරණය සක්‍රීය කරයි.
මනු 343726

3
මම චැට් එකේ සඳහන් L <= Rකළ පරිදි, !(R < L)ඒ වෙනුවට ප්‍රකාශ කළ හැකිය !(L > R). දෘ-ප්‍රශස්තිකරණ ප්‍රකාශනවල අමතර පේළියක් ඉතිරි කළ හැකිය (තවද එය Boost.Operators විසින් ක්‍රියාත්මක කරන ආකාරය ද වේ).
TemplateRex

495

C ++ හි ක්‍රියාකරු අධි බර පැටවීමේ මූලික රීති තුන

C ++ හි ක්‍රියාකරු අධි බර පැටවීමේදී ඔබ අනුගමනය කළ යුතු මූලික නීති තුනක් තිබේ. එවැනි සියලු නීති මෙන්ම, ඇත්ත වශයෙන්ම ව්යතිරේක පවතී. සමහර විට මිනිසුන් ඔවුන්ගෙන් බැහැර වී ඇති අතර ප්‍රති come ලය නරක කේතයක් නොවීය, නමුත් එවැනි ධනාත්මක අපගමනයන් ස්වල්පයක් හා බොහෝ දුරට වේ. අවම වශයෙන්, මා දුටු එවැනි අපගමනය 100 න් 99 ක්ම යුක්ති සහගත නොවේ. කෙසේ වෙතත්, එය 1000 න් 999 ක් විය හැකිය. එබැවින් ඔබ පහත සඳහන් නීතිවලට ඇලී සිටීම හොඳය.

  1. ක්‍රියාකරුවෙකුගේ අර්ථය පැහැදිලිවම පැහැදිලි හා අවිවාදිත නොවන සෑම අවස්ථාවකදීම එය අධික ලෙස පටවා නොගත යුතුය. ඒ වෙනුවට, හොඳින් තෝරාගත් නමක් සහිත ශ්‍රිතයක් සපයන්න.
    මූලික වශයෙන්, අධික ලෙස පැටවීම සඳහා වන පළමු හා ප්‍රධානතම රීතිය, එහි හදවතේම මෙසේ පවසයි: එය නොකරන්න . එය අමුතු දෙයක් ලෙස පෙනෙන්නට පුළුවන, මන්ද ක්‍රියාකරු අධික ලෙස පැටවීම පිළිබඳව බොහෝ දේ දැනගත යුතු අතර ලිපි, පොත් පරිච්ඡේද සහ වෙනත් පා xts යන් මේ සියල්ල සමඟ කටයුතු කරයි. නමුත් පැහැදිලිව පෙනෙන මෙම සාක්ෂි තිබියදීත් , ක්‍රියාකරු අධික ලෙස පැටවීම සුදුසු අවස්ථා කිහිපයක් තිබේ. හේතුව, යෙදුම් වසමේ ක්‍රියාකරුගේ භාවිතය හොඳින් දන්නා සහ අවිවාදිත නම් මිස ක්‍රියාකරුවෙකුගේ යෙදුම පිටුපස ඇති අර්ථ නිරූපණය තේරුම් ගැනීම දුෂ්කර ය. ජනප්‍රිය විශ්වාසයන්ට පටහැනිව, මෙය කිසිසේත්ම සිදු නොවේ.

  2. සෑම විටම ක්රියාකරුගේ ප්රසිද්ධ අර්ථ නිරූපණයට ඇලී සිටින්න.
    සී ++ අධික ලෙස පටවන ලද ක්‍රියාකරුවන්ගේ අර්ථ නිරූපණයට කිසිදු සීමාවක් නොමැත. ඔබේ සම්පාදකයා ද්විමය+ක්‍රියාකරුගේ නිවැරදි ක්‍රියාකාරිත්වයෙන් අඩු කිරීමට අවශ්‍යකේතය සතුටින් භාර ගනී. කෙසේ වෙතත්, එවැනි ක්‍රියාකරුවෙකුගේ පරිශීලකයින් ප්‍රකාශනයa + bඅඩුකිරීමට කිසි විටෙකත් සැක නොකරනුaඇතb. ඇත්ත වශයෙන්ම, යෙදුම් වසමේ ක්‍රියාකරුගේ අර්ථ නිරූපණය අවිවාදිත යැයි මෙය උපකල්පනය කරයි.

  3. අදාළ මෙහෙයුම් සමූහයකින් සෑම විටම සෑම දෙයක්ම සපයන්න.
    ක්රියාකරුවන් එකිනෙකා හා වෙනත් මෙහෙයුම් වලට සම්බන්ධ වේ. ඔබගේ වර්ගය සහය දක්වන්නේ නම්a + b, පරිශීලකයින්ටද ඇමතීමට හැකි වනු ඇතැයි අපේක්ෂා කෙරේa += b. එය උපසර්ග වර්ධක සඳහා සහය දක්වන්නේ නම්++a, ඔවුන් දa++වැඩකිරීමට බලාපොරොත්තුවේ. ඔවුන්ට පරීක්ෂා කළ හැකි නම්a < b, ඔවුන් නිසැකවම අපේක්ෂා කරන්නේද යන්න පරීක්ෂා කිරීමට හැකි වනු ඇතa > b. ඔවුන්ට ඔබේ වර්ගය පිටපත්-තැනීමට හැකි නම්, පැවරුම ද ක්‍රියාත්මක වනු ඇතැයි ඔවුහු අපේක්ෂා කරති.


සාමාජිකයා සහ සාමාජික නොවන සාමාජිකයා අතර තීරණයට ඉදිරියට යන්න .


16
මේ කිසිවක් උල්ලං which නය කරන මා දන්නා එකම දෙය boost::spiritලොල් ය.
බිලී ඔනේල්

66
Ill බිලී: සමහරුන්ට අනුව, +නූල් සම්මුතියකට අතවර කිරීම උල්ලං is නය කිරීමකි, නමුත් එය මේ වන විට හොඳින් ස්ථාපිත වී ඇති ප්‍රැක්සිස් බවට පත්ව ඇත. 90 දශකයේ දී මේ සඳහා ද්විමය භාවිතා කළ බව මා දුටු ගෙදර හැදූ නූල් පන්තියක් මට මතකයි &(ස්ථාපිත ප්‍රැක්සිස් සඳහා BASIC වෙත යොමු වන්න). එහෙත්, ඔව්, එය ලිබරල් ලිබ් එකට දැමීමෙන් මූලික වශයෙන් මෙය ගල් ගසන්න. අපයෝජනය <<සහ >>IO, BTW සඳහාද මෙයම වේ. වම් මාරුව පැහැදිලිවම නිමැවුම් මෙහෙයුම වන්නේ ඇයි? මොකද අපි හැමෝම අපේ පළමු "හෙලෝ, ලෝකය" දුටු විට ඒ ගැන ඉගෙන ගත්තා. අයදුම්පත. වෙනත් හේතුවක් නොමැතිව.
sbi

5
urcuriousguy: ඔබට එය පැහැදිලි කළ යුතු නම්, එය පැහැදිලිවම පැහැදිලි හා අවිවාදිත ය. ඒ හා සමානව ඔබට අධික බර පැටවීම ගැන සාකච්ඡා කිරීමට හෝ ආරක්ෂා කිරීමට අවශ්‍ය නම්.
sbi

5
bsbi: "තුල්‍ය සමාලෝචනය" සැමවිටම හොඳ අදහසකි. මට නම් නරක ලෙස තෝරාගත් ක්‍රියාකරු නරක ලෙස තෝරාගත් ක්‍රියාකාරී නාමයට වඩා වෙනස් නොවේ (මම බොහෝ දේ දුටුවෙමි). ක්රියාකරු යනු කාර්යයන් පමණි. තවත් නොඅඩු විය යුතුය. නීති එකම ය. අදහසක් හොඳ දැයි තේරුම් ගැනීමට, හොඳම ක්‍රමය වන්නේ තේරුම් ගැනීමට කොපමණ කාලයක් ගතවේද යන්න තේරුම් ගැනීමයි. (එබැවින්, සම වයස්කරුවන්ගේ සමාලෝචනය අත්‍යවශ්‍ය වේ, නමුත් සම වයසේ මිතුරන් තෝරා ගත යුත්තේ ප්‍රවාදයෙන් හා අගතියෙන් තොර පුද්ගලයන් අතර ය.)
එමිලියෝ ගරාවග්ලියා

5
@sbi මට නම්, එකම පැහැදිලිව හා අවිවාදිත කරුණ operator==නම් එය සමානතා සම්බන්ධතාවයක් විය යුතු බවයි (IOW, ඔබ සං N ා නොවන NaN භාවිතා නොකළ යුතුය). බහාලුම්වල බොහෝ ප්‍රයෝජනවත් සමානතා සම්බන්ධතා ඇත. සමානාත්මතාවය යන්නෙන් අදහස් කරන්නේ කුමක්ද? " aසමාන bබව අදහස් වන්නේ" aහා bඑම ගණිතමය අගය ඇත. (NaN නොවන) ගණිතමය වටිනාකම පිළිබඳ සංකල්පය floatපැහැදිලිය, නමුත් බහාලුමක ගණිතමය වටිනාකමට විවිධාකාර (පුනරාවර්තන) ප්‍රයෝජනවත් අර්ථ දැක්වීම් තිබිය හැකිය. සමානාත්මතාවයේ ප්‍රබලම නිර්වචනය වන්නේ “ඒවා එකම වස්තූන්” වන අතර එය නිෂ් .ල ය.
කුතුහලයෙන්

265

C ++ හි ක්‍රියාකරු අධි පැටවීමේ සාමාන්‍ය සින්ටැක්ස්

C ++ හි සාදන ලද වර්ග සඳහා ක්‍රියාකරුවන්ගේ අර්ථය ඔබට වෙනස් කළ නොහැක, ක්‍රියාකරුවන් අධික ලෙස පැටවිය හැක්කේ පරිශීලක අර්ථ දක්වන ලද වර්ග 1 සඳහා පමණි . එනම්, අවම වශයෙන් එක් ඔපෙරන්ඩ් එකක් වත් පරිශීලක අර්ථ දක්වන ආකාරයේ විය යුතුය. වෙනත් අධි බර පැටවූ කාර්යයන් මෙන්ම, ක්‍රියාකරුවන්ට නිශ්චිත පරාමිතීන් සමූහයක් සඳහා එක් වරක් පමණක් පැටවිය හැකිය.

සියලුම ක්‍රියාකරුවන් C ++ තුළ අධික ලෙස පැටවිය නොහැක. අධික ලෙස පැටවිය නොහැකි ක්‍රියාකරුවන් අතර: . :: sizeof typeid .*සහ C ++ හි ඇති එකම ත්‍රික ක්‍රියාකරු,?:

C ++ හි අධික ලෙස පැටවිය හැකි ක්‍රියාකරුවන් අතර මේවා නම්:

  • අංක ගණිත ක්‍රියාකරුවන්: + - * / %සහ += -= *= /= %=(සියලුම ද්විමය ඉන්ෆික්ස්); + -(unary උපසර්ගය); ++ --(unary උපසර්ගය සහ postfix)
  • බිටු හැසිරවීම: & | ^ << >>සහ &= |= ^= <<= >>=(සියලුම ද්විමය තොරතුරු); ~(unary උපසර්ගය)
  • බූලියන් වීජ ගණිතය: == != < > <= >= || &&(සියලුම ද්විමය ඉන්ෆික්ස්); !(unary උපසර්ගය)
  • මතක කළමනාකරණය: new new[] delete delete[]
  • ව්‍යංග පරිවර්තන ක්‍රියාකරුවන්
  • miscellany: = [] -> ->* , (සියලුම ද්විමය තොරතුරු); * &(සියලුම ඒකීය උපසර්ගය) ()(ශ්‍රිත ඇමතුම, n-ary infix)

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

C ++ හි, ක්‍රියාකරුවන් විශේෂ නම් සහිත ශ්‍රිත ස්වරූපයෙන් අධික ලෙස පටවනු ලැබේ . වෙනත් කාර්යයන් මෙන්ම, අධික ලෙස පටවා ඇති ක්‍රියාකරුවන් සාමාන්‍යයෙන් ඔවුන්ගේ වම් ඔපෙරන්ඩ් වර්ගයේ සාමාජික ශ්‍රිතයක් ලෙස හෝ සාමාජික නොවන කාර්යයන් ලෙස ක්‍රියාත්මක කළ හැකිය. ඔබට තෝරා ගැනීමට නිදහස තිබේද නැතහොත් එකක් භාවිතා කිරීමට බැඳී සිටීද යන්න නිර්ණායක කිහිපයක් මත රඳා පවතී. 2 ඒ ඒකජ ක්රියාකරු @3 , වස්තුවක් x යෙදිය, එක්කෝ පළ කළහ ඇත operator@(x)හෝ x.operator@(). ඒ ද්විමය infix ක්රියාකරු @, වස්තූන් සඳහා ඉල්ලුම් xසහ y, එක්කෝ ලෙස හැඳින්වේ operator@(x,y)හෝ x.operator@(y). 4

සාමාජික නොවන කාර්යයන් ලෙස ක්‍රියාත්මක කරන ක්‍රියාකරුවන් සමහර විට ඔවුන්ගේ ක්‍රියාකාරිත්වයේ මිතුරා වේ.

1 “පරිශීලක අර්ථ දැක්වීම” යන යෙදුම තරමක් නොමඟ යවන සුළු විය හැකිය. C ++ මඟින් සාදන ලද වර්ග සහ පරිශීලක අර්ථ දක්වන ලද වර්ග අතර වෙනස හඳුනා ගනී. මුල් ඒවාට අයත් වන්නේ උදාහරණයක් ලෙස int, char සහ double; සම්මත පුස්තකාලයෙන් ඇතුළුව සියලුම ව්‍යුහාත්මක, පංති, යුනියන් සහ එනුම් වර්ග අයත් වන්නේ ඒවා පරිශීලකයින් විසින් නිර්වචනය කර නොමැති වුවද ය.

2 මෙම නිති අසන ප්‍රශ්නවල පසු කොටසක මෙය ආවරණය කෙරේ .

3 මෙම @C ++ වලංගු ක්රියාකරු මම තැන් දරණුව ලෙස එය භාවිතා ඇයි වන නොවේ.

4 C ++ එකම මිශ්ර ක්රියාකරු වුවමනාවන් කළ නොහැකි වූ එකම n-ජලනල ක්රියාකරු සෑම විටම සාමාජිකයෙකු ශ්රිතයක් ලෙස ක්රියාත්මක කළ යුතු ය.


C ++ හි ක්‍රියාකරු අධි බර පැටවීමේ මූලික රීති තුනට ඉදිරියට යන්න .


~ඒකීය උපසර්ගය මිස ද්විමය ඉන්ෆික්ස් නොවේ.
mrkj

1
.*අධි බර පැටවිය නොහැකි ක්‍රියාකරුවන්ගේ ලැයිස්තුවෙන් අස්ථානගත වී ඇත.
celticminstrel

1
At මාටින් මට අවශ්‍ය වූයේ සැබෑ ක්‍රියාකරුවෙකු වෙනුවට ස්ථාන දරු දැරියක් භාවිතා කිරීමටයි, මෙය විශේෂ ක්‍රියාකරුවෙකු ගැන නොවන බව පැහැදිලි කිරීම සඳහා, නමුත් ඒ සියල්ලටම අදාළ වේ. තවද, ඔබට C ++ ක්‍රමලේඛකයෙකු වීමට අවශ්‍ය නම්, කුඩා මුද්‍රණය කෙරෙහි පවා අවධානය යොමු කිරීමට ඔබ ඉගෙන ගත යුතුය. :)
sbi

1
@HR: ඔබ මෙම මාර්ගෝපදේශය කියවා ඇත්නම්, වැරැද්ද කුමක්දැයි ඔබ දැන ගනු ඇත. මම සාමාන්‍යයෙන් යෝජනා කරන්නේ ඔබ ප්‍රශ්නයට සම්බන්ධ පළමු පිළිතුරු තුන කියවිය යුතු බවයි. එය ඔබගේ ජීවිතයේ පැය භාගයකට වඩා වැඩි නොවිය යුතු අතර ඔබට මූලික අවබෝධයක් ලබා දෙයි. ඔබට පසුව සොයා බැලිය හැකි ක්‍රියාකරු-විශේෂිත සින්ටැක්ස්. ඔබගේ විශේෂිත ගැටළුව මඟින් ඔබ operator+()සාමාජික ශ්‍රිතයක් ලෙස අධික ලෙස පැටවීමට උත්සාහ කරන නමුත් එයට නිදහස් ශ්‍රිතයක අත්සන ලබා දී ඇත. මෙහි බලන්න .
sbi

1
@sbi: මම දැනටමත් පළමු පෝස්ට් තුන කියවා ඇති අතර ඒවා සෑදීමට ස්තූතියි. :) මම ගැටලුව විසඳීමට උත්සාහ කරමි, එසේ නොමැතිනම් එය වෙනම ප්‍රශ්නයකින් ඇසීම වඩා හොඳ යැයි මම සිතමි. අපට ජීවිතය එතරම් පහසු කරවීම ගැන නැවතත් ස්තූතියි! : ඩී
හොසේන් රහ්නාමා

253

සාමාජිකයා සහ සාමාජික නොවන සාමාජිකයා අතර තීරණය

ද්විමය ක්‍රියාකරුවන් =(පැවරුම), [](අරාව දායකත්වය), ->(සාමාජික ප්‍රවේශය) මෙන්ම n-ary ()(ශ්‍රිත ඇමතුම්) ක්‍රියාකරු සැමවිටම සාමාජික කාර්යයන් ලෙස ක්‍රියාත්මක කළ යුතුය , මන්ද භාෂාවේ වාක්‍ය ඛණ්ඩයට ඒවා අවශ්‍ය වේ.

අනෙකුත් ක්‍රියාකරුවන් සාමාජිකයන් ලෙස හෝ සාමාජිකයන් නොවන අය ලෙස ක්‍රියාත්මක කළ හැකිය. කෙසේ වෙතත්, ඒවායින් සමහරක් සාමාන්‍යයෙන් සාමාජික නොවන කාර්යයන් ලෙස ක්‍රියාත්මක කළ යුතුය, මන්ද ඒවායේ වම් ක්‍රියාකාරිත්වය ඔබට වෙනස් කළ නොහැකි බැවිනි. මේවායින් වඩාත් කැපී පෙනෙන වන්නේ ආදාන සහ ප්‍රතිදාන ක්‍රියාකරුවන් වන <<අතර >>, ඒවායේ වම් ක්‍රියාකාරිත්වය ඔබට වෙනස් කළ නොහැකි සම්මත පුස්තකාලයේ ප්‍රවාහ පන්ති වේ.

සාමාජික ශ්‍රිතයක් හෝ සාමාජික නොවන ශ්‍රිතයක් ලෙස ක්‍රියාත්මක කිරීමට ඔබ තෝරා ගත යුතු සියලුම ක්‍රියාකරුවන් සඳහා, තීරණය කිරීම සඳහා පහත දැක්වෙන නියමය භාවිතා කරන්න:

  1. එය ඒකීය ක්‍රියාකරුවෙකු නම් , එය සාමාජික ශ්‍රිතයක් ලෙස ක්‍රියාත්මක කරන්න.
  2. ද්විමය ක්‍රියාකරුවෙකු ඔපෙරන්ඩ් දෙකම එක හා සමානව සලකන්නේ නම් (එය ඒවා නොවෙනස්ව පවතී), මෙම ක්‍රියාකරු සාමාජික නොවන ශ්‍රිතයක් ලෙස ක්‍රියාත්මක කරන්න.
  3. ද්විමය ක්රියාකරු කරන්නේ නම් නෑ එහි operands දෙකම ප්රතිකාර සමානව (සාමාන්යයෙන් එය එහි වාම යන අගයද වෙනස් වනු ඇත), එය එය කිරීමට ප්රයෝජනවත් විය හැකිය සාමාජික එය යන අගයද පෞද්ගලික කොටස් වෙත ප්රවේශ වීමට ඇති නම්, එහි වාම යන අගයද ගේ වර්ගයේ ශ්රිතය.

ඇත්ත වශයෙන්ම, සියලු නීති රීති මෙන්, ව්යතිරේක පවතී. ඔබට වර්ගයක් තිබේ නම්

enum Month {Jan, Feb, ..., Nov, Dec}

ඔබට ඒ සඳහා වර්ධක හා අඩුකිරීමේ ක්‍රියාකරුවන් අධික ලෙස පැටවීමට අවශ්‍ය නම්, ඔබට මෙය සාමාජික ශ්‍රිතයක් ලෙස කළ නොහැක, මන්ද C ++ හි, enum වර්ග වලට සාමාජික ශ්‍රිත තිබිය නොහැක. එබැවින් ඔබ එය නිදහස් කාර්යයක් ලෙස අධික ලෙස පැටවිය යුතුය. හා operator<()පන්ති අර්ථ දැක්වීම තුළ සාමාජික ශ්රිතය පේළිගත ලෙස සිදු වූ විට පන්ති සැකිල්ල තුළ පතරෙහි පන්ති සැකිල්ල සඳහා ලිවීමට සහ කියවීමට පහසු විය. නමුත් මේවා සැබවින්ම දුර්ලභ ව්‍යතිරේකයකි.

(කෙසේ වෙතත්, නම් ඔබට ව්යතිරේකයක් කරන්න, ප්රශ්නය අමතක කරන්න එපා const-ness මෙම අගයද මන්ත්රී කාර්යයන් සඳහා, නිසැක බවට පත් වෙයි, ඒ thisතර්කය. සාමාජිකයෙකු නොවන ශ්රිතයක් ලෙස ක්රියාකරු ලෙස එහි වාම-වඩාත් තර්කය ගන්නා බව නම් constසඳහන් , සාමාජික ශ්රිතයක් ලෙස එම ක්රියාකරු ඇති කිරීමට අවශ්ය constකිරීමට අවසානයේ දී *thisඑය constසඳහන්.)


අධි බර පැටවීම සඳහා පොදු ක්‍රියාකරුවන් වෙත දිගටම යන්න .


9
C ලදායී C ++ හි ඇති ඔසු සූටර්ගේ අයිතමය (හෝ එය C ++ කේතීකරණ ප්‍රමිති ද?) පවසන්නේ පංතියේ වටපිටාව වැඩි කිරීම සඳහා සාමාජික නොවන මිතුරන්ගේ නොවන ක්‍රියාකාරකම් සාමාජික ක්‍රියාකාරිත්වයට වඩා කැමති විය යුතු බවයි. IMHO, සංසරණ හේතුව ඔබේ මාපට ඇඟිල්ලට වඩා ප්‍රමුඛස්ථානය ගනී, නමුත් එය ඔබගේ නියමානුකූල රීතියේ ගුණාත්මක අගය අඩු නොකරයි.
paercebal

8
erPercebal: C ලදායී C ++ යනු මේයර්ස් විසිනි, C ++ කේතීකරණ ප්‍රමිති සූටර් විසිනි. ඔබ සඳහන් කරන්නේ කුමන එකකටද? කෙසේ වෙතත්, මම operator+=()සාමාජිකයෙකු නොවීම යන අදහසට අකමැතියි . එහි වම් අතෙහි ක්‍රියාකාරිත්වය වෙනස් කළ යුතුය, එබැවින් අර්ථ දැක්වීම අනුව එහි අභ්‍යන්තරය ගැඹුරට හාරා ගත යුතුය. එය සාමාජිකයෙකු නොකිරීමෙන් ඔබට ලැබෙන්නේ කුමක්ද?
sbi

9
@sbi: C ++ කේතීකරණ ප්‍රමිති (සූටර්) හි 44 වන අයිතමය නොබැඳි මිත්‍ර නොවන කාර්යයන් ලිවීමට කැමැත්තක් දක්වන්න , ඇත්ත වශයෙන්ම, එය අදාළ වන්නේ ඔබට පන්තියේ පොදු අතුරුමුහුණත පමණක් භාවිතා කර මෙම ශ්‍රිතය ලිවිය හැකි නම් පමණි. ඔබට නොහැකි නම් (හෝ එය ක්‍රියාකාරීත්වයට අහිතකර ලෙස බාධාවක් වනු ඇත), එවිට ඔබ එය සාමාජිකයෙකු හෝ මිතුරෙකු බවට පත් කළ යුතුය.
මැතිව් එම්.

3
@sbi: අපොයි, ective ලදායී, සුවිශේෂී ... මම නම් මිශ්‍ර කිරීම පුදුමයක් නොවේ. කෙසේ වෙතත් වාසිය වන්නේ වස්තුවකට පුද්ගලික / ආරක්ෂිත දත්ත වලට ප්‍රවේශය ඇති ශ්‍රිත ගණන හැකිතාක් සීමා කිරීමයි. මේ ආකාරයෙන්, ඔබ ඔබේ පන්තියේ වටපිටාව වැඩි කරන අතර එහි නඩත්තුව / පරීක්ෂා කිරීම / පරිණාමය පහසු කරයි.
paercebal

12
@sbi: එක් උදාහරණයක්. අපි කියමු ඔබ ක්‍රම operator +=සහ appendක්‍රම දෙකම සමඟ සංගීත පන්තියක් කේත කරන බව . මෙම appendක්‍රමය වඩාත් සම්පූර්ණයි, මන්ද ඔබට පරාමිතිකයේ උපස්ථරයක් දර්ශකයේ සිට දර්ශකය n -1 දක්වා එකතු කළ හැකි බැවිනි: ඇමතුම් එකතු කිරීම සහ සමඟ append(string, start, end)තාර්කිකව පෙනේ . එම අවස්ථාවේදී, උපග්‍රන්ථය සාමාජික ක්‍රමයක් විය හැකි නමුත් සාමාජිකයෙකු වීමට අවශ්‍ය නොවන අතර එය සාමාජිකයෙකු නොවන බවට පත් කිරීමෙන් සංගීත ඉනාර්ඩ්ස් සමඟ කේත සෙල්ලම් කිරීමේ ප්‍රමාණය අඩු වනු ඇත, එබැවින් එය හොඳ දෙයකි .... ^ _ ^ ...+=start = 0end = string.sizeoperator +=
paercebal

165

පරිවර්තන ක්‍රියාකරුවන් (පරිශීලක අර්ථ දක්වන ලද පරිවර්තන ලෙසද හැඳින්වේ)

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

ව්‍යංග පරිවර්තන ක්‍රියාකරුවන් (C ++ 98 / C ++ 03 සහ C ++ 11)

ව්‍යාජ පරිවර්තන ක්‍රියාකරුවෙකු විසින් පරිශීලකයා විසින් නිර්වචනය කරන ලද වර්ගයක වටිනාකම වෙනත් වර්ගයකට ව්‍යංගයෙන් පරිවර්තනය කිරීමට ( intසහ අතර පරිවර්තනය වැනි long) සම්පාදකයාට ඉඩ දෙයි .

පහත දැක්වෙන්නේ ව්‍යංග පරිවර්තන ක්‍රියාකරු සහිත සරල පන්තියකි:

class my_string {
public:
  operator const char*() const {return data_;} // This is the conversion operator
private:
  const char* data_;
};

එක්-තර්ක සාදන්නන් මෙන් ව්‍යංග පරිවර්තන ක්‍රියාකරුවන් යනු පරිශීලක අර්ථ දක්වන ලද පරිවර්තනයකි. අධි බර පැටවූ ශ්‍රිතයකට ඇමතුමක් ගැලපීමට උත්සාහ කරන විට සම්පාදකයින් විසින් පරිශීලක අර්ථ දක්වන ලද පරිවර්තනයක් ලබා දෙනු ඇත.

void f(const char*);

my_string str;
f(str); // same as f( str.operator const char*() )

මුලදී මෙය ඉතා ප්‍රයෝජනවත් බව පෙනේ, නමුත් මෙහි ඇති ගැටළුව නම් ව්‍යංග පරිවර්තනය එය අපේක්ෂා නොකරන විට පවා ආරම්භ වීමයි. පහත දැක්වෙන කේතයේ, අගයක් නොවන void f(const char*)බැවින් අමතනු ඇත , එබැවින් පළමුවැන්න නොගැලපේ:my_string()

void f(my_string&);
void f(const char*);

f(my_string());

ආරම්භකයින් පහසුවෙන් මෙම වැරැද්ද ලබා ගන්නා අතර පළපුරුදු C ++ ක්‍රමලේඛකයින් පවා සමහර විට පුදුමයට පත් වන්නේ සම්පාදකයා තමන් සැක නොකළ අධික බරක් තෝරා ගන්නා බැවිනි. පැහැදිලි පරිවර්තන ක්‍රියාකරුවන් විසින් මෙම ගැටළු අවම කර ගත හැකිය.

පැහැදිලි පරිවර්තන ක්‍රියාකරුවන් (සී ++ 11)

ව්‍යංග පරිවර්තන ක්‍රියාකරුවන් මෙන් නොව, පැහැදිලි පරිවර්තන ක්‍රියාකරුවන් ඔබ අපේක්ෂා නොකරන විට කිසි විටෙකත් ඒවාට සම්බන්ධ නොවනු ඇත. පහත දැක්වෙන්නේ පැහැදිලි පරිවර්තන ක්‍රියාකරුවෙකු සහිත සරල පන්තියකි:

class my_string {
public:
  explicit operator const char*() const {return data_;}
private:
  const char* data_;
};

සැලකිල්ලට ගන්න explicit. දැන් ඔබ ව්‍යංග පරිවර්තන ක්‍රියාකරුවන්ගෙන් අනපේක්ෂිත කේතය ක්‍රියාත්මක කිරීමට උත්සාහ කරන විට, ඔබට සම්පාදක දෝෂයක් ලැබේ:

prog.cpp: 'int main ()' ශ්‍රිතයේ:
prog.cpp: 15: 18: දෝෂය: 'f (my_string)' ඇමතුමට ගැලපෙන ශ්‍රිතයක් නොමැත.
prog.cpp: 15: 18: සටහන: අපේක්ෂකයින්:
prog.cpp: 11: 10: සටහන: අවලංගු f (my_string &)
prog.cpp: 11: 10: සටහන: 'my_string' සිට 'my_string &' දක්වා 1 වන තර්කය සඳහා පරිවර්තනයක් නොමැත.
prog.cpp: 12: 10: සටහන: අවලංගු f (const char *)
prog.cpp: 12: 10: සටහන: 'my_string' සිට 'const char *' දක්වා 1 වන තර්කය සඳහා දන්නා පරිවර්තනයක් නොමැත.

පැහැදිලි වාත්තු ක්‍රියාකරුට ආයාචනා කිරීම සඳහා, ඔබ භාවිතා කළ static_castයුත්තේ, සී-ස්ටයිල් කාස්ට් හෝ ඉදිකිරීම් ශෛලියේ වාත්තු (එනම් T(value)) ය.

කෙසේ වෙතත්, මේ සඳහා එක් ව්‍යතිරේකයක් ඇත: සම්පාදකයාට ව්‍යංගයෙන් පරිවර්තනය වීමට අවසර ඇත bool. ඊට අමතරව, සම්පාදකයාට එය පරිවර්තනය කිරීමෙන් පසු වෙනත් ව්‍යංග පරිවර්තනයක් කිරීමට අවසර නැත bool(සම්පාදකයෙකුට වරකට ව්‍යාජ පරිවර්තන 2 ක් කිරීමට අවසර ඇත, නමුත් උපරිම වශයෙන් පරිශීලක අර්ථ දක්වන ලද පරිවර්තනයක් 1 ක් පමණි).

සම්පාදකයා "අතීතය" නොතබන හෙයින් bool, පැහැදිලි පරිවර්තන ක්‍රියාකරුවන් දැන් ආරක්ෂිත බූල් මෝඩයේ අවශ්‍යතාවය ඉවත් කරයි . නිදසුනක් ලෙස, C ++ 11 ට පෙර ඇති ස්මාර්ට් පොයින්ටර්ස්, සමෝධානික වර්ග වලට පරිවර්තනය වීම වැළැක්වීම සඳහා ආරක්ෂිත බූල් මෝඩය භාවිතා කළේය. C ++ 11 හි, ස්මාර්ට් පොයින්ටර්ස් ඒ වෙනුවට පැහැදිලි ක්‍රියාකරුවෙකු භාවිතා කරයි, මන්දයත් සම්පාදකයාට යම් වර්ගයක් පැහැදිලිවම බූල් බවට පරිවර්තනය කිරීමෙන් පසුව එය අනුකලනයකට ව්‍යංගයෙන් පරිවර්තනය කිරීමට ඉඩ නොදේ.

දිගටම වැඩියෙන් newහාdelete .


148

අධි බර පැටවීම newසහdelete

සටහන: සමග මෙය ගනුදෙනු කාරක රීති වැඩියෙන් කnewහාdeleteසමග නොව, ක්රියාත්මක කිරීම වැනි වුවමනාවන් ක්රියාකරුවන්. වැඩිපුර බර පැටවීමේ අර්ථ නිරූපණයnew සහ deleteඔවුන්ගේම නිතර අසනු ලබන ප්‍රශ්න , ක්‍රියාකරු අධි බර පැටවීම යන මාතෘකාව තුළ මට කිසි විටෙකත් එය සාධාරණය කළ නොහැකිය.

මූලික කරුණු

C ++, ඔබ ලිවීමට විට නව ප්රකාශනය වැනි new T(arg)පළමුව: මෙම ප්රකාශනය ඇගයීමට ලක් කරන විට වේ කරුණු දෙකක් සිදු operator newඅමු මතකය ලබා ගැනීම සඳහා උපයෝගී වේ, පසුව සුදුසු ඉදිකිරීමටත් Tවලංගු වස්තුවක් බවට අමු මතක හැරී සඳහා උපයෝගී වේ. ඒ හා සමානව, ඔබ වස්තුවක් මකා දැමූ විට, පළමුව එහි විනාශ කරන්නා ලෙස හැඳින්වේ, පසුව මතකය නැවත ලබා දෙනු operator deleteලැබේ.
මෙම මෙහෙයුම් දෙකම සුසර කිරීමට C ++ ඔබට ඉඩ සලසයි: මතක කළමනාකරණය සහ වෙන් කළ මතකයේ වස්තුව ඉදිකිරීම / විනාශ කිරීම. දෙවැන්න පන්තියක් සඳහා ඉදිකිරීම්කරුවන් සහ විනාශ කරන්නන් ලිවීමෙනි. මනාව සුසර කිරීමේ මතක කළමනාකරණය ඔබේම operator newසහ ලිවීමෙන් සිදු කෙරේ operator delete.

ක්‍රියාකරු අධි බර පැටවීමේ මූලික නීති වලින් පළමුවැන්න - එය නොකරන්න - විශේෂයෙන් අධික ලෙස පැටවීම newසහ delete. මෙම ක්‍රියාකරුවන් අධික ලෙස පැටවීමට ඇති එකම හේතු වන්නේ කාර්ය සාධන ගැටළු සහ මතක අවහිරතා වන අතර බොහෝ අවස්ථාවන්හීදී, භාවිතා කරන ඇල්ගොරිතමවල වෙනස්වීම් වැනි වෙනත් ක්‍රියා, මතක කළමනාකරණය වෙනස් කිරීමට උත්සාහ කරනවාට වඩා වැඩි පිරිවැයක් / ලාභ අනුපාතයක් ලබා දෙනු ඇත .

C ++ සම්මත පුස්තකාලය පූර්ව නිශ්චිත newහා deleteක්‍රියාකරුවන් සමූහයක් සමඟ පැමිණේ . වැදගත්ම ඒවා නම්:

void* operator new(std::size_t) throw(std::bad_alloc); 
void  operator delete(void*) throw(); 
void* operator new[](std::size_t) throw(std::bad_alloc); 
void  operator delete[](void*) throw(); 

පළමු දෙක වස්තුවක් සඳහා මතකය වෙන් කිරීම / අවලංගු කිරීම, දෙවන දෙක වස්තු සමූහයක් සඳහා. ඔබ මේවායේ ඔබේම අනුවාදයන් සපයන්නේ නම්, ඒවා අධික ලෙස පටවන්නේ නැත, නමුත් ඒවා සම්මත පුස්තකාලයෙන් ප්‍රතිස්ථාපනය කරන්න.
ඔබ අධික ලෙස පැටවෙන්නේ නම්, ඔබ එය කිසි විටෙකත් ඇමතීමට අදහස් operator newනොකලත්, ගැලපීම අධික ලෙස පැටවිය යුතුය operator delete. හේතුව, නව ප්‍රකාශනයක් තක්සේරු කිරීමේදී ඉදිකිරීම්කරුවෙකු විසි කළහොත්, ධාවන කාල පද්ධතිය මඟින් මතකය operator deleteගැලපෙන පරිදි නැවත ලබා දෙනු ඇත operator new. එම වස්තුව නිර්මාණය කිරීම සඳහා මතකය වෙන් කිරීම සඳහා කැඳවනු ලැබීය. ඔබ ගැලපීමක් ලබා නොදෙන්නේ නම් operator delete, පෙරනිමිය හැඳින්වෙන්නේ සෑම විටම පාහේ වැරදිය.
ඔබ අධික ලෙස පැටවුවහොත් newසහ delete, අරාව ප්‍රභේදයන් අධික ලෙස පැටවීම ගැනද සලකා බැලිය යුතුය.

ස්ථානගත කිරීම new

C ++ නව සහ මකන ක්‍රියාකරුවන්ට අමතර තර්ක ගැනීමට ඉඩ දෙයි.
ඊනියා ස්ථානගත කිරීම් නව ඔබට යම් ලිපිනයකින් වස්තුවක් නිර්මාණය කිරීමට ඉඩ දෙයි.

class X { /* ... */ };
char buffer[ sizeof(X) ];
void f()
{ 
  X* p = new(buffer) X(/*...*/);
  // ... 
  p->~X(); // call destructor 
} 

සම්මත පුස්තකාලය මේ සඳහා නව සහ මකාදැමීමේ ක්‍රියාකරුවන්ගේ සුදුසු බර පැටවීම සමඟ පැමිණේ:

void* operator new(std::size_t,void* p) throw(std::bad_alloc); 
void  operator delete(void* p,void*) throw(); 
void* operator new[](std::size_t,void* p) throw(std::bad_alloc); 
void  operator delete[](void* p,void*) throw(); 

operator deleteX හි ඉදිකිරීම්කරු ව්‍යතිරේකයක් විසි නොකරන්නේ නම්, ඉහත දක්වා ඇති නව ස්ථානගත කිරීම් සඳහා වන උදාහරණ කේතයේ කිසි විටෙකත් කැඳවනු නොලැබේ.

ඔබට අධික ලෙස පැටවීම newසහ deleteවෙනත් තර්ක සමඟද කළ හැකිය . නව ස්ථානගත කිරීම සඳහා වන අතිරේක තර්කය මෙන්ම, මෙම තර්ක ද යතුරු පදයෙන් පසුව වරහන් තුළ ලැයිස්තුගත කර ඇත new. Historical තිහාසික හේතූන් මත, එවැනි විචල්‍යයන් බොහෝ විට ස්ථානගත කිරීම නව යැයි ද හැඳින්වේ, ඒවායේ තර්ක නිශ්චිත ලිපිනයකට වස්තුවක් තැබීම සඳහා නොවුනත්.

පන්ති විශේෂිත නව සහ මකන්න

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

class my_class { 
  public: 
    // ... 
    void* operator new();
    void  operator delete(void*,std::size_t);
    void* operator new[](size_t);
    void  operator delete[](void*,std::size_t);
    // ... 
}; 

මේ අනුව අධික ලෙස පැටවීම, නව සහ මකාදැමීම් ස්ථිතික සාමාජික ශ්‍රිත මෙන් ක්‍රියා කරයි. වස්තු සඳහා my_class, std::size_tතර්කය සැමවිටම වනු ඇත sizeof(my_class). කෙසේ වෙතත්, මෙම ක්‍රියාකරුවන් ව්‍යුත්පන්න පංතිවල ගතිකව වෙන් කරන ලද වස්තු සඳහා ද කැඳවනු ලැබේ , එම අවස්ථාවේ දී එය ඊට වඩා විශාල විය හැකිය.

ගෝලීය නව සහ මකන්න

ගෝලීය නව හා මකාදැමීම සඳහා, සම්මත පුස්තකාලයේ කලින් නිර්වචනය කළ ක්‍රියාකරුවන් අපගේම දෑ සමඟ ප්‍රතිස්ථාපනය කරන්න. කෙසේ වෙතත්, මෙය කලාතුරකින් කළ යුතුව ඇත.


11
ගෝලීය ක්‍රියාකරු නව සහ මකාදැමීම සාමාන්‍යයෙන් කාර්ය සාධනය සඳහා වන බව මම එකඟ නොවෙමි: ඊට පටහැනිව, එය සාමාන්‍යයෙන් දෝෂ සොයා ගැනීම සඳහා වේ.
Yttrill

1
ඔබ අධික ලෙස පටවන ලද නව ක්‍රියාකරුවෙකු භාවිතා කරන්නේ නම්, මකාදැමීමේ ක්‍රියාකරුට ගැලපෙන තර්ක සමඟ සැපයිය යුතු බව ද ඔබ සටහන් කළ යුතුය. ඔබ පවසන්නේ ගෝලීය නව / මකාදැමීමේ කොටසේ එය එතරම් උනන්දුවක් නොදක්වන බවයි.
Yttrill

13
T වයිට්‍රිල් ඔබ දේවල් අවුල් කරනවා. මෙම අර්ථය වුවමනාවන් යයි. “ක්‍රියාකරු අධි බර පැටවීම” යන්නෙන් අදහස් කරන්නේ අර්ථය අධික ලෙස පැටවීමයි. වචනානුසාරයෙන් කාර්යයන් අධික ලෙස පටවා ඇති බවක් එයින් අදහස් නොකෙරේ, සහ විශේෂයෙන් ක්‍රියාකරු නව විසින් සම්මතයේ අනුවාදය අධික ලෙස පටවන්නේ නැත. bsbi ප්‍රතිවිරුද්ධ දේ කියා නැත. “අධි බර පැටවීමේ එකතු කිරීමේ ක්‍රියාකරු” යැයි පැවසීම සාමාන්‍ය දෙයක් වන බැවින් එය “නව බර පැටවීම” ලෙස හැඳින්වීම සාමාන්‍ය දෙයකි.
ජොහැන්නස් ෂෝබ් -

1
@sbi: බලන්න (හෝ හොඳ වෙත සබැඳිය) gotw.ca/publications/mill15.htm . සමහර විට nothrowනව භාවිතා කරන පුද්ගලයින් කෙරෙහි එය හොඳ පුරුද්දක් පමණි .
ඇලෙක්සැන්ඩර් සී

1
"ඔබ ගැලපෙන ක්‍රියාකරු මකාදැමීමක් ලබා නොදෙන්නේ නම්, පෙරනිමිය හැඳින්වෙන්නේ" -> ඇත්ත වශයෙන්ම, ඔබ කිසියම් තර්ක එකතු කර ගැලපෙන මකාදැමීමක් නිර්මාණය නොකරන්නේ නම්, කිසිදු ක්‍රියාකරු මකාදැමීමක් කිසිසේත් නොකියන අතර ඔබට මතක කාන්දුවක් ඇත. (15.2.2, වස්තුව සතු ගබඩාව අවලංගු කරනු ලබන්නේ සුදුසු ... ක්‍රියාකරු මකාදැමීමක් හමු වුවහොත් පමණි)
dascandy

46

operator<<වස්තුවක් ප්‍රවාහනය කිරීම සඳහා std::coutහෝ ගොනුවකට සාමාජික ශ්‍රිතයක් ලෙස ක්‍රියා කළ නොහැක්කේ ඇයි ?

ඔබට ඇති බව කියමු:

struct Foo
{
   int a;
   double b;

   std::ostream& operator<<(std::ostream& out) const
   {
      return out << a << " " << b;
   }
};

එය ලබා දී ඇති විට, ඔබට භාවිතා කළ නොහැක:

Foo f = {10, 20.0};
std::cout << f;

සිට operator<<සාමාජිකයෙකු ශ්රිතයක් ලෙස බහුලය Foo, ක්රියාකරු වන LHS තිබිය යුතු වන Fooවස්තුවක්. එයින් අදහස් වන්නේ, ඔබ භාවිතා කිරීමට අවශ්‍ය වනු ඇත:

Foo f = {10, 20.0};
f << std::cout

එය ඉතා බුද්ධිමත් නොවන.

ඔබ එය සාමාජික නොවන ශ්‍රිතයක් ලෙස අර්ථ දක්වන්නේ නම්,

struct Foo
{
   int a;
   double b;
};

std::ostream& operator<<(std::ostream& out, Foo const& f)
{
   return out << f.a << " " << f.b;
}

ඔබට භාවිතා කිරීමට හැකි වනු ඇත:

Foo f = {10, 20.0};
std::cout << f;

එය ඉතා බුද්ධිමත් ය.

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.