Rvalues, lvalues, xvalues, glvalues ​​සහ prvalues ​​යනු කුමක්ද?


1376

C ++ 03 හි ප්‍රකාශනයක් rvalue හෝ lvalue වේ.

C ++ 11 හි ප්‍රකාශනයක් විය හැක්කේ:

  1. rvalue
  2. lvalue
  3. xvalue
  4. glvalue
  5. prvalue

කාණ්ඩ දෙකක් කාණ්ඩ පහක් බවට පත්ව ඇත.

  • මෙම නව ප්‍රකාශන වර්ග මොනවාද?
  • මෙම නව කාණ්ඩයන් දැනට පවතින අගය හා lvalue කාණ්ඩ සමඟ සම්බන්ධ වන්නේ කෙසේද?
  • C ++ 0x හි ඇති අගය සහ lvalue කාණ්ඩ C ++ 03 හි ඇති ආකාරයටම සමානද?
  • මෙම නව කාණ්ඩ අවශ්‍ය වන්නේ ඇයි? මෙම ලැබේ WG21 දෙවිවරුන් පමණක් අපට හුදු මිනිසුන් ව්යාකූල කිරීමට උත්සාහ?

9
H ෆිලිප් පොටර්: සී ++ 03 දී? ඔව්. සම්මත අගයක්-සිට-අගයක් දක්වා පරිවර්තනයක් ඇති බැවින්, අගයක් අගයක් ලෙස භාවිතා කළ හැකිය.
ජේම්ස් මැක්නෙලිස්

14
Y ටයිලර්: "ඔබට එය පැවරිය හැකි නම්, එය අගයකි, එසේ නොමැති නම් එය අගයකි." -> වැරදියි, ඔබට පන්ති අගයන්ට පැවරිය හැකිය : string("hello") = string("world").
fredoverflow

4
මෙය අගය කාණ්ඩය බව සලකන්න. ප්‍රකාශන වලට තිබිය හැකි තවත් ගුණාංග තිබේ. මේවාට බිට්-ෆීල්ඩ් (සත්‍ය / අසත්‍ය), තාවකාලික (සත්‍ය / අසත්‍ය) සහ වර්ගය (එහි වර්ගය) ඇතුළත් වේ.
ජොහැන්නස් ෂෝබ් - litb

30
මම හිතන්නේ ඉහත ෆ්‍රෙඩ්ගේ සබැඳිය මෙහි ඇති ඕනෑම පිළිතුරකට වඩා හොඳයි. නමුත් සබැඳිය මිය ගොස් ඇත. එය වෙත ගෙන යන ලද්දේ: straustrup.com/terminology.pdf
ආර්. මාටින්හෝ ෆර්නැන්ඩස්

74
C ++ හි ඔබේ වර්ගවල පවා වර්ග තිබේ
නීල්ස්බෝට්

Answers:


639

මෙම ලේඛනය එතරම් කෙටි නොවන හැඳින්වීමක් ලෙස සේවය කරනු ඇතැයි මම සිතමි : n3055

සමූල re ාතනය ආරම්භ වූයේ චලනය වන අර්ථ නිරූපණයෙනි. අපට චලනය කළ හැකි සහ පිටපත් කළ නොහැකි ප්‍රකාශන ඇති විට, හදිසියේම නීති ග්‍රහණය කර ගැනීම පහසුය, චලනය කළ හැකි ප්‍රකාශන සහ කුමන දිශාවටද යන්න වෙන්කර හඳුනා ගැනීම.

කෙටුම්පත මත පදනම්ව මා අනුමාන කරන දෙයින්, r / l අගය වෙනස එලෙසම පවතී, දේවල් චලනය වන සන්දර්භය තුළ පමණක් අවුල් සහගත වේ.

ඒවා අවශ්‍යද? බොහෝ විට අපි නව විශේෂාංග නැති කර ගැනීමට කැමති නම් නොවේ. නමුත් වඩා හොඳ ප්‍රශස්තිකරණයකට ඉඩ දීම සඳහා අපි ඒවා වැලඳ ගත යුතුය.

උපුටා ගැනීම n3055 :

  • lvalue (ඊනියා ඓතිහාසික, lvalues පැවරුමක් ප්රකාශනයේ වම් අත පැත්තේ පෙනී සිටිය හැකි නිසා) උත්සවයකට හෝ වස්තුවක් නම් කරන. [උදාහරණය: Eදර්ශක වර්ගයේ ප්‍රකාශනයක් නම්, *E එය ලක්ෂ්‍යයට යොමු වන වස්තුව හෝ ශ්‍රිතය ගැන සඳහන් කරන අගනා ප්‍රකාශනයකි E . තවත් උදාහරණයක් ලෙස, ශ්‍රිතයක් ආපසු යැවීමේ වර්ගය lvalue යොමු කිරීමක් ලෙස හැඳින්වීමේ ප්‍රති result ලය lvalue වේ.]
  • xvalue (ක "යුද වැදුණු" අගය) ද (එහි සම්පත් උදාහරණයක් ලෙස, ඉදිරිපත් කළ හැකිය ඒ නිසා බව) සාමාන්යයෙන් එහි ජීවිත කාලය අවසන් අසල, වස්තුවක් සඳහන් කරයි. Xvalue යනු rvalue යොමුවලට සම්බන්ධ ඇතැම් ප්‍රකාශනවල ප්‍රති result ලයකි. [උදාහරණය: ප්‍රතිලාභ වර්ගයක් වන අගය යොමු කිරීමක් වන ශ්‍රිතයක් ඇමතීමේ ප්‍රති x ලය xvalue වේ.]
  • glvalue ( "පොදු" lvalue) යනු lvalue හෝ xvalue .
  • rvalue (ඊනියා ඓතිහාසික, rvalues පැවරුමක් ප්රකාශනයේ දකුණු අත පැත්තේ පෙනී සිටිය හැකි නිසා) ක xvalue, තාවකාලික වස්තුව හෝ එහි subobject, හෝ වස්තුවක් එක්ක නැති බව අගය වේ.
  • prvalue ( "පිරිසිදු" rvalue) යනු xvalue නොවන බව ඉතා rvalue වේ. [උදාහරණය: ආපසු යැවීමේ වර්ගය යොමු නොවන ශ්‍රිතයක් ඇමතීමේ ප්‍රති pr ලය අගයයි]

නව නාමකරණය හඳුන්වාදීමේ ප්‍රති result ලයක් ලෙස සිදුවී ඇති ප්‍රමිතියේ නිශ්චිත වෙනස්කම් පෙන්නුම් කරන හෙයින්, ප්‍රශ්නයට ලක්වූ ලේඛනය මෙම ප්‍රශ්නය සඳහා හොඳ යොමු කිරීමකි.


ස්තූතියි, මෙම පිළිතුර ඇත්තෙන්ම ප්‍රයෝජනවත් වේ! නමුත් මගේ සම්පාදකයා xvalues ​​සහ prvalues ​​සඳහා ඔබගේ උදාහරණ සමඟ එකඟ නොවේ; ඒවා හරියටම ප්‍රතිවිරුද්ධයයි. Rvalue යොමු කිරීම මඟින් නැවත පැමිණීම මට අගයක් ලබා දෙන අතර අගය අනුව නැවත පැමිණීම මට xvalue ලබා දෙයි. ඔබ ඒවා මිශ්‍ර කළාද, නැත්නම් මගේ පරීක්ෂණ ඇඳ කැඩී තිබේද? මම මෙය GCC 4.6.1, clang (svn වෙතින්) සහ MSVC සමඟ උත්සාහ කළ අතර ඔවුන් සියල්ලන්ම එකම හැසිරීමක් පෙන්නුම් කරයි.
කිම් ග්‍රොස්මන්

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

4
විවිධ ප්‍රකාශන පරීක්ෂා කිරීම සඳහා මම මෙතැන් සිට මැක්‍රෝස් භාවිතා කරමි: stackoverflow.com/a/6114546/96963 ඔවුන් දේවල් වැරදි ලෙස විනිශ්චය කිරීම විය හැකිය.
කිම් ග්‍රොස්මන්

1
Xvalue එකතු කිරීම චලනය වන අර්ථ නිරූපණය සඳහා නොවේ. Lvalue සහ rvalue යන දෙකම සමඟ පමණක්, චලනය වන අර්ථ නිරූපණය, පරිපූර්ණ ඉදිරි හා අගය යොමු කිරීම තවමත් හොඳින් ක්‍රියාත්මක වේ. මම හිතන්නේ xvalue යනු ඩෙක්ලයිටයිප් ක්‍රියාකරු සඳහා පමණි: ඔපෙරන්ඩ් ප්‍රකාශනය xvalue නම්, ඩෙක්ලයිටයිප් මඟින් අගය යොමු කිරීමේ වර්ගය ලබා දේ.
ලිගන්ඩ්

1
U මුහම්මද්කාක් "සෑම ප්‍රකාශනයක්ම අගයක් හෝ අගයක් වේ": එය සත්‍යයකි; සම්මත (හෝ n3055 ලේඛනය) එය අසත්‍ය යැයි නොකියයි. මෙම වාක්‍යය ඉක්මවා යාමට හේතුව ඔබ ලේඛනයේ අනුවාද දෙකක් අතර වෙනස්කම් දෙස බලා සිටීමයි. වඩාත් නිවැරදි පැහැදිලි කිරීමක් එකතු කිරීමෙන් පසුව එය අතිරික්ත බවට පත් වූ නිසා ද sentence ුවම ඉවත් කරන ලදි.
උපරිම

341

මෙම නව ප්‍රකාශන වර්ග මොනවාද?

මෙම FCD (n3092) විශිෂ්ට ලෙස අර්ථ ඇත:

- lvalue (පැවරුම් ප්‍රකාශනයක වම් පසින් lvalues ​​දිස්විය හැකි නිසා ically තිහාසිකව ඊනියා) ශ්‍රිතයක් හෝ වස්තුවක් නියම කරයි. [උදාහරණය: E යනු දර්ශක වර්ගයේ ප්‍රකාශනයක් නම්, * E යනු E ලක්ෂ්‍ය කරන වස්තුව හෝ ශ්‍රිතය වෙත යොමු කරන අගනා ප්‍රකාශනයකි. තවත් උදාහරණයක් ලෙස, ශ්‍රිතයක් ආපසු යැවීමේ වර්ගය lvalue යොමු කිරීමක් ලෙස හැඳින්වීමේ ප්‍රති result ලය lvalue වේ. උදාහරණයක් ලෙස]

- xvalue (“eXpiring” අගයක්) යනු සාමාන්‍යයෙන් වස්තුවක ආයු කාලය අවසන් වීමට ආසන්නය (උදාහරණයක් ලෙස එහි සම්පත් ගෙනයාමට). Xvalue යනු අගය යොමු කිරීම් (8.3.2) සම්බන්ධ වන ඇතැම් ප්‍රකාශනවල ප්‍රති result ලයකි. [උදාහරණය: ප්‍රතිලාභ වර්ගයක් වන අගය යොමු කිරීමක් වන ශ්‍රිතයක් ඇමතීමේ ප්‍රති x ලය xvalue වේ. උදාහරණයක් ලෙස]

- glvalue (“සාමාන්‍යකරණය කළ” lvalue) යනු lvalue හෝ xvalue වේ.

- අගයක් (ඊනියා, ically තිහාසිකව, පැවරුම් ප්‍රකාශනයක දකුණු පැත්තේ අගයන් දිස්විය හැකි නිසා) යනු xvalue, තාවකාලික වස්තුවක් (12.2) හෝ එහි උප විෂය හෝ වස්තුවක් හා සම්බන්ධ නොවන අගයකි.

- ප්‍රාවලියක් (“පිරිසිදු” අගය) යනු xvalue නොවන අගයකි. [උදාහරණය: නැවත පැමිණීමේ වර්ගය යොමු නොවන ශ්‍රිතයක් ඇමතීමේ ප්‍රති result ලය අගයක් වේ. 12, 7.3e5, හෝ සත්‍ය වැනි වචනාර්ථයක වටිනාකම ද අගයක් වේ. උදාහරණයක් ලෙස]

සෑම ප්‍රකාශනයක්ම මෙම වර්ගීකරණයේ මූලික වර්ගීකරණයන්ගෙන් එකකට අයත් වේ: lvalue, xvalue, හෝ prvalue. ප්‍රකාශනයක මෙම ගුණාංගය එහි අගය කාණ්ඩය ලෙස හැඳින්වේ. [සටහන: 5 වන වගන්තියේ එක් එක් ගොඩනඟන ලද ක්‍රියාකරුගේ සාකච්ඡාවෙන් පෙන්නුම් කරන්නේ එය ලබා දෙන වටිනාකම සහ එය අපේක්ෂා කරන ක්‍රියාකාරිත්වයේ අගය කාණ්ඩයයි. නිදසුනක් ලෙස, ගොඩනංවන ලද පැවරුම් ක්‍රියාකරුවන් අපේක්ෂා කරන්නේ වම් ඔපෙරන්ඩ් අගය අගයක් වන අතර දකුණු ඔපෙරන්ඩ් අගය අගයක් වන අතර එහි ප්‍රති val ලයක් ලෙස අගයක් ලබා දෙනු ඇත. පරිශීලක-නිර්වචනය කළ ක්‍රියාකරුවන් යනු කාර්යයන් වන අතර, ඔවුන් අපේක්ෂා කරන අගයන් සහ අස්වැන්න තීරණය වන්නේ ඒවායේ පරාමිතිය සහ ප්‍රතිලාභ වර්ග අනුව ය. සටහන

3.10 අගයන් සහ අගයන් වුවද සම්පූර්ණ කොටස කියවීමට මම යෝජනා කරමි .

මෙම නව කාණ්ඩයන් දැනට පවතින අගය හා lvalue කාණ්ඩ සමඟ සම්බන්ධ වන්නේ කෙසේද?

යළි:

වර්ගීකරණය

C ++ 0x හි ඇති අගය සහ lvalue කාණ්ඩ C ++ 03 හි ඇති ආකාරයටම සමානද?

චලිත අර්ථකථන විශේෂයෙන් චලිත අර්ථකථන හඳුන්වාදීමත් සමඟ විකාශනය වී ඇත.

මෙම නව කාණ්ඩ අවශ්‍ය වන්නේ ඇයි?

එබැවින් එම පියවර ඉදිකිරීම / පැවරුම නිර්වචනය කර සහාය විය හැකිය.


55
මම මෙහි රූපසටහනට කැමතියි. "සෑම වර්ගීකරණයක්ම මෙම වර්ගීකරණයේ මූලික වර්ගීකරණයකට අයත් වේ: lvalue, xvalue, හෝ prvalue" යනුවෙන් පිළිතුර ආරම්භ කිරීම ප්‍රයෝජනවත් යැයි මම සිතමි . එවිට එම මූලික පංති තුන ඒකාබද්ධ වී ග්ලැවල් අගය සහ අගය ගණනය කිරීම සඳහා රූප සටහන භාවිතා කිරීම පහසුය.
ආරොන් මැක්ඩේඩ්

2
"is glvalue" යනු "prvalue නොවේ" යන්නට සමාන වන අතර "rvalue" යනු "lvalue නොවේ" යන්නට සමාන වේ.
ව්ලැඩිමීර් රෙෂෙට්නිකොව්

2
මෙය මට වඩාත්ම උදව් කළේ: bajamircea.github.io/assets/2016-04-07-move-forward/… (වටිනාකම් කාණ්ඩවල වෙන් රූප සටහන)
ජෝන් පී

1
AAaronMcDaid හායි, ඔබට / යමෙකුට පිළිතුරු දිය හැකි නම් ඉක්මන් ප්‍රශ්නය ... ඇයි නම් නොකරන්නේ glvalue ලෙස lvalueහා lvalueලෙස plvalueස්ථාවර වීමට,?
විජේ චව්ඩා

185

මම ඔබේ අවසාන ප්‍රශ්නය සමඟ ආරම්භ කරමි:

මෙම නව කාණ්ඩ අවශ්‍ය වන්නේ ඇයි?

C ++ ප්‍රමිතියේ ප්‍රකාශනයක අගය කාණ්ඩය සමඟ කටයුතු කරන බොහෝ නීති අඩංගු වේ. සමහර රීති වල අගය සහ අගය අතර වෙනසක් ඇත. උදාහරණයක් ලෙස, අධි බර විභේදනය සම්බන්ධයෙන් ගත් විට. වෙනත් නීති රීති මගින් ග්ලැවුලූ සහ ප්‍රව්වුලූ අතර වෙනසක් ඇති කරයි. නිදසුනක් ලෙස, ඔබට අසම්පූර්ණ හෝ වියුක්ත වර්ගයක් සහිත ග්ලූවෙල් එකක් තිබිය හැකි නමුත් අසම්පූර්ණ හෝ වියුක්ත වර්ගයක් සහිත අගයක් නොමැත. මෙම පාරිභාෂිතය ඇතිවීමට පෙර ඇත්ත වශයෙන්ම lvalue / rvalue ලෙස හැඳින්වෙන glvalue / prvalue අතර වෙනස හඳුනාගත යුතු නීති රීති සහ ඒවා නොදැනුවත්වම වැරදියි හෝ රීතියට ලා සහ පැහැදිලි කිරීම් සහ ව්‍යතිරේක රාශියක් අඩංගු විය. rvalue යොමුව ... ". එබැවින්, ග්ලූවෙල්ස් සහ ප්‍රව්ලූස් යන සංකල්ප වලට ඔවුන්ගේ නම පමණක් ලබා දීම හොඳ අදහසක් සේ පෙනේ.

මෙම නව ප්‍රකාශන වර්ග මොනවාද? මෙම නව කාණ්ඩයන් දැනට පවතින අගය හා lvalue කාණ්ඩ සමඟ සම්බන්ධ වන්නේ කෙසේද?

C ++ 98 සමඟ අනුකූල වන lvalue සහ rvalue යන වචන තවමත් අප සතුව ඇත. අපි අගයයන් උප කාණ්ඩ දෙකකට බෙදුවෙමු, එනම් xvalues ​​සහ prvalues, අපි lvalues ​​සහ xvalues ​​glvalues ​​ලෙස හඳුන්වමු. Xvalues ​​යනු නම් නොකළ rvalue යොමු කිරීම් සඳහා නව ආකාරයේ වටිනාකම් කාණ්ඩයකි. සෑම ප්‍රකාශනයක්ම මෙම තුනෙන් එකකි: lvalue, xvalue, prvalue. වෙන් රූප සටහනක් මේ වගේ වනු ඇත:

    ______ ______
   /      X      \
  /      / \      \
 |   l  | x |  pr  |
  \      \ /      /
   \______X______/
       gl    r

කාර්යයන් සහිත උදාහරණ:

int   prvalue();
int&  lvalue();
int&& xvalue();

නම් කරන ලද rvalue යොමු කිරීම් lvalues ​​බව අමතක නොකරන්න:

void foo(int&& t) {
  // t is initialized with an rvalue expression
  // but is actually an lvalue expression itself
}

165

මෙම නව කාණ්ඩ අවශ්‍ය වන්නේ ඇයි? WG21 දෙවිවරුන් අපව හුදු මනුෂ්‍යයන් ලෙස පටලවා ගැනීමට උත්සාහ කරනවාද?

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

ඔබ ගමන් කළ යුත්තේ එය ආරක්ෂිතව කළ විට පමණි.

මෙම වර්ගීකරණයන් පවතින්නේ එබැවිනි: සාරධර්ම ඒවායින් ආරක්ෂා වීමට ආරක්ෂිත තැන ගැන කතා කිරීමට හැකි වීම සහ එය නොමැති තැන සාරධර්ම ගැන කතා කිරීම.

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

යමක් ගෙනයාම ආරක්ෂිත වන තත්වයන් මෙන්න:

  1. එය තාවකාලික හෝ උප විෂයයක් වන විට. (අගය)
  2. පරිශීලකයා එය ගෙන යන ලෙස පැහැදිලිවම පවසා ඇති විට .

ඔබ මෙය කරන්නේ නම්:

SomeType &&Func() { ... }

SomeType &&val = Func();
SomeType otherVal{val};

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

මෙහි ඇත්තේ එක් ගැටළුවක් පමණි; ඔබ එය ගෙනයාමට ඉල්ලා සිටියේ නැත . ඔහ්, ඔබට කියන්න පුළුවන් &&හෝඩුවාවක් තිබිය යුතුයි, නමුත් එය නීතිය කඩ කළා යන කාරණය වෙනස් කරන්නේ නැහැ. valතාවකාලික නොවේ, මන්ද තාවකාලිකයන්ට නම් නොමැත. ඔබ තාවකාලික ආයු කාලය දීර් have කර ඇති නමුත් එයින් අදහස් වන්නේ එය තාවකාලික නොවන බවයි ; එය වෙනත් ඕනෑම සිරස් විචල්‍යයකට සමානය.

එය තාවකාලික නොවේ නම් සහ ඔබ එය ගෙනයාමට ඉල්ලා නොසිටියේ නම්, චලනය වැරදිය.

පැහැදිලි විසඳුම වන්නේ valඅගයක් සෑදීමයි . මෙයින් අදහස් කරන්නේ ඔබට එයින් ඉවත් විය නොහැකි බවයි. හරි හොදයි; එය නම් කර ඇත, එබැවින් එහි අගයක්.

ඔබ එය කළ පසු, ඔබට තව දුරටත් SomeType&&එකම දේ අදහස් කරන බව පැවසිය නොහැක. ඔබ දැන් නම් කර ඇති rvalue යොමු කිරීම් සහ නම් නොකළ rvalue යොමු කිරීම් අතර වෙනසක් කර ඇත. හොඳයි, නම් කරන ලද අගයන් යොමු කිරීම් lvalues ​​වේ; ඉහත අපගේ විසඳුම එයයි. ඉතින් අපි නම් නොකල තක්සේරු අගයන් ( Funcඉහළින් ලැබෙන ප්‍රතිලාභ අගය ) ලෙස හඳුන්වන්නේ කුමක්ද?

ඔබට අගයකින් ගමන් කළ නොහැකි නිසා එය අගයක් නොවේ. අපි අවශ්ය නැවත හැරී විසින් ඉවත් කිරීමට හැකි විය &&; යමක් ගෙනයාමට ඔබට පැහැදිලිව කිව හැක්කේ කෙසේද? std::moveසියල්ලට පසු නැවත පැමිණෙන්නේ එයයි . එය අගයක් නොවේ (පැරණි විලාසිතාව), මන්ද එය සමීකරණයක වම් පැත්තෙහි විය හැකි බැවිනි (ඇත්ත වශයෙන්ම දේවල් ටිකක් සංකීර්ණයි, මෙම ප්‍රශ්නය සහ පහත දැක්වෙන අදහස් බලන්න). එය අගයක් හෝ අගයක් නොවේ; ඒක අලුත් දෙයක්.

අප සතුව ඇත්තේ අගයක් ලෙස සැලකිය හැකි වටිනාකමක් මිස එය ව්‍යංගයෙන් චලනය කළ හැකි ය. අපි එය xvalue ලෙස හඳුන්වමු.

Xvalues ​​යනු අනෙක් අගයන් දෙක ලබා ගැනීමට අපව පොළඹවන බව සලකන්න:

  • ප්‍රාවලියක් යනු සැබවින්ම පෙර වර්ගයේ අගය සඳහා නව නමකි, එනම් ඒවා xvalues නොවන rvalues ​​වේ.

  • ග්ලැවල්ස් යනු එක් කණ්ඩායමක xvalues ​​සහ lvalues ​​එකමුතුවයි, මන්ද ඒවා පොදු ගුණාංග රාශියක් බෙදා ගනී.

ඉතින් ඇත්ත වශයෙන්ම, ඒ සියල්ල xvalues ​​දක්වා පහළට ගමන් කරන අතර නිශ්චිත හා නිශ්චිත ස්ථාන වලට පමණක් චලනය සීමා කිරීමේ අවශ්‍යතාවය. එම ස්ථාන අර්ථ දැක්වෙන්නේ වර්ගීකරණ කාණ්ඩයෙනි; prvalues ​​යනු ව්‍යංග චලනයන් වන අතර xvalues ​​යනු පැහැදිලි චලනයන් වේ ( std::movexvalue ලබා දෙයි).


11
H තෝමස්: එය උදාහරණයක්; එය ප්‍රතිලාභ අගය නිර්මාණය කරන්නේ කෙසේද යන්න ගැටළුවක් නොවේ. වැදගත් වන්නේ එය නැවත ලබා දීමයි &&.
නිකොල් බෝලස්

1
සටහන: අගයන් සමීකරණයක වම් පසින් විය හැකිය - එසේම X foo(); foo() = X;... මෙම මූලික හේතුව නිසා මට ඉහත විශිෂ්ට පිළිතුර අවසානය දක්වාම අනුගමනය කළ නොහැක, මන්ද ඔබ සැබවින්ම වෙනස හඳුනා ගන්නේ නව xvalue, සහ පැරණි විලාසිතාවේ අගය, එය lhs මත විය හැකි බව මත පදනම් වේ.
ඩෑන් නිසෙන්බෝම්

1
Xපංතියක් වීම; X foo();ශ්‍රිත ප්‍රකාශයක් foo() = X();වීම සහ කේත රේඛාවක් වීම. (මම ලකුණු වරහන් දෙවන මාලාවක් ඉතිරි foo() = X();ඉස්මතු, මගේ ඉහත ලේඛකයාගේ.) මම මේ භාවිතය සමග පල ප්රශ්නයක් සඳහා බලන්න stackoverflow.com/questions/15482508/...
දාන් Nissenbaum

1
An ඩැනිස්සෙන්බාම් "පැවරුම් ප්‍රකාශනයේ වම් පසින් xvalue විය නොහැක" - ඇයි නැත්තේ? Ideone.com/wyrxiT
මිහායිල්

1
බුද්ධිමත් පිළිතුර. මෙය නිසැකවම මෙහි හොඳම පිළිතුරයි. නව වටිනාකම් කාණ්ඩ හඳුන්වාදීම සහ ඊට පෙර සිදු වූ දේ පිළිබඳව එය මට තාර්කිකත්වයක් ලබා දුන්නේය.
නිකොස්

138

IMHO, එහි අර්ථය පිළිබඳ හොඳම පැහැදිලි කිරීම අපට ස්ට්‍රෝස්ට්‍රප් + ලබා දුන්නේ ඩැනියෙල් සන්ඩෝර් සහ මොහාන්ගේ උදාහරණ සැලකිල්ලට ගනිමිනි :

Stroustrup:

දැන් මම බරපතල ලෙස කනස්සල්ලට පත්ව සිටියෙමි. පැහැදිලිවම අප ගමන් කළේ අවුල් ජාලයකට හෝ අවුල් ජාලයකට හෝ දෙකටම ය. කුමන ගුණාංග (සාරධර්ම) ස්වාධීනද යන්න විශ්ලේෂණය කිරීම සඳහා මම දිවා ආහාරය ගත කළෙමි. තිබුණේ ස්වාධීන දේපල දෙකක් පමණි:

  • has identity - එනම් ලිපිනය, දර්ශකයක්, පරිශීලකයාට පිටපත් දෙකක් සමානද යන්න තීරණය කළ හැකිය.
  • can be moved from - එනම්, යම් නිශ්චිත, නමුත් වලංගු තත්වයක “පිටපතක්” ප්‍රභවයක් වෙත යාමට අපට අවසර ඇත

මෙය හරියටම වටිනාකම් වර්ග තුනක් ඇති බව නිගමනය කිරීමට මට හේතු විය (negative ණාත්මක බවක් දැක්වීමට ලොකු අකුරක් භාවිතා කිරීමේ රීජෙක්ස් අංකන උපක්‍රමය භාවිතා කිරීම - මම ඉක්මන් විය):

  • iM: අනන්‍යතාවයක් ඇති අතර එයින් ඉවත් කළ නොහැක
  • im: අනන්‍යතාවයක් ඇති අතර එය වෙනත් ස්ථානයකින් ගෙන යා හැකිය (උදා: අගය අගයක් යොමු අගයකට යොමු කිරීමේ ප්‍රති result ලය)
  • Im: අනන්‍යතාවයක් නොමැති අතර එයින් ඉවත් කළ හැකිය.

    සිව්වන හැකියාව, IM(අනන්‍යතාවයක් නොමැති අතර ගෙන යා නොහැක C++) වෙනත් භාෂාවක (හෝ, මම සිතන පරිදි) ප්‍රයෝජනවත් නොවේ .

සාරධර්මවල මෙම මූලික වර්ගීකරණයන්ට අමතරව, ස්වාධීන ගුණාංග දෙකට අනුරූප වන පැහැදිලි සාමාන්‍යකරණයන් දෙකක් අපට තිබේ:

  • i: අනන්‍යතාවයක් ඇත
  • m: සිට ගෙන යා හැකිය

මෙම රූප සටහන පුවරුවට දැමීමට මෙය මට මඟ පෑදීය: රූප විස්තරය මෙහි ඇතුළත් කරන්න

නම් කිරීම

(ලේබල් වමට මෙම කරුණු දෙක: මම හිතන්නේ අපි නම පමණක් සීමිත නිදහස ඇති බව නිරීක්ෂණය iMහා i) විධිමත් අඩු හෝ වැඩි සමග ජනතාව කැඳවා ඇති මොනවාද lvaluesසහ දකුණු පස ඇති කරුණු දෙකක් (ලේබල් mසහ Im) විධිමත් අඩු හෝ වැඩි සමග දේ මිනිස්සු කැඳවා rvaluesඇත. මෙය අපගේ නම් කිරීම තුළින් පිළිබිඹු විය යුතුය. එනම්, වම් “කකුලට” Wසම්බන්ධ නම් තිබිය යුතු lvalueඅතර දකුණු “කකුලට” Wඅදාළ නම් තිබිය යුතු බව rvalue.මම සටහන් කරමි. මෙම සමස්ත සාකච්ඡාව / ගැටලුව පැන නගින්නේ තක්සේරු යොමු කිරීම් සහ චලන අර්ථකථන හඳුන්වාදීමෙනි. මෙම අදහස් හුදෙක් යුක්තිසහගත rvaluesහා සමන්විත ස්ට්‍රැචීගේ ලෝකයේ නොපවතී lvalues. ඒ අදහස් ඒ බව කවුරුහරි නිරීක්ෂණය කළා

  • සෑම valueඑකක්ම එක් lvalueහෝ අrvalue
  • An lvalueයනු a නොවන අතර rvaluean rvalueනොවේlvalue

අපගේ වි ness ානය තුළ ගැඹුරින් කාවැදී ඇති අතර, ඉතා ප්‍රයෝජනවත් ගුණාංග සහ කෙටුම්පත් ප්‍රමිතිය පුරාම මෙම ද්විභාෂාවේ අංශුමාත්‍ර සොයාගත හැකිය. එම දේපල ආරක්ෂා කර ගත යුතු බව අපි සියලු දෙනාම එකඟ වෙමු (ඒවා නිවැරදිව කරන්න). මෙය අපගේ නම් කිරීමේ තේරීම් තවදුරටත් සීමා කළේය. සම්මත පුස්තකාල වචනවල rvalueඅර්ථය m(සාමාන්‍යකරණය) සඳහා භාවිතා කරන බව මම නිරීක්ෂණය කළෙමි, එවිට සම්මත පුස්තකාලයේ අපේක්ෂාව සහ පෙළ ආරක්ෂා කර ගැනීම සඳහා දකුණු පස පහළ ලක්ෂ්‍යය නම් Wකළ යුතුය. rvalue.

මෙය නම් කිරීම පිළිබඳ කේන්ද්‍රීය සාකච්ඡාවකට තුඩු දුන්නේය. පළමුව, අප විසින් තීරණය lvalue.කළ යුතුව තිබුණේ lvalueඅදහස් කළ යුතුද iMනැතිනම් සාමාන්‍යකරණයද i? ඩග් ග්‍රෙගර්ගේ නායකත්වයෙන්, අපි මූලික භාෂාවේ වචන ලැයිස්තුගත කර ඇති අතර එම වචනය lvalueඑක් හෝ වෙනත් අර්ථයක් සඳහා සුදුසුකම් ලබා ඇත. ලැයිස්තුවක් සාදන ලද අතර බොහෝ අවස්ථාවන්හීදී සහ වඩාත්ම උපක්‍රමශීලී / අස්ථාවර පා text වල lvalueදැනට අදහස් iMවේ. Lvalue හි සම්භාව්‍ය අර්ථය මෙයයි, මන්ද “පැරණි දිනවල” කිසිවක් චලනය නොවූ බැවිනි; moveයනු නව සංකල්පයකි C++0x. එසේම, W lvalueලබා දෙන ස්ථානයේ ඉහළම ස්ථානය නම් කිරීම මඟින් සෑම අගයක්ම lvalueහෝ එකක් rvalueවන නමුත් දෙකම නොවන දේපල අපට ලබා දේ .

ඒ නිසා, ඉහළ වම් ස්ථානය Wවේ lvalueහා පහළ දකුණු කාරණය rvalue.බව පහළ වම් හා දකුණු පස ඉහළ ලකුණු කරන්න අදහස් කරන්නේ කුමක්ද? පහළ වම්පස යනු සම්භාව්‍ය අගයන් සාමාන්‍යකරණය කිරීමකි. එබැවින් එය generalized lvalue.අපි නම් කළ අතර glvalue.ඔබට කෙටි යෙදුම ගැන විග්‍රහ කළ හැකිය, නමුත් (මම හිතන්නේ) තර්කනය සමඟ නොවේ. බැරෑරුම් ලෙස භාවිතා කිරීම generalized lvalue කෙසේ හෝ කෙටියෙන් කෙටියෙන් දක්වනු ඇතැයි අපි උපකල්පනය කළෙමු , එබැවින් අපි එය වහාම සිදු කිරීම වඩා හොඳය (හෝ අවදානම් ව්‍යාකූලතා). ඩබ්ලිව් හි ඉහළ දකුණු ලක්ෂ්‍යය පහළ දකුණට වඩා අඩු සාමාන්‍යය (දැන්, වෙනදා මෙන්, හැඳින්වේ rvalue). එම ලක්ෂ්‍යය නිරූපණය කරන්නේ ඔබට චලනය කළ හැකි වස්තුවක මුල් පිරිසිදු සංකල්පය වන අතර එය නැවත යොමු කළ නොහැකි නිසා (විනාශ කරන්නෙකු හැර). මම specialized rvalueඊට වෙනස්ව වාක්‍ය ඛණ්ඩයට කැමතියිgeneralized lvalue නමුත්pure rvalueකෙටියෙන් කෙටියෙන් prvalueජය ගැනීම (සහ බොහෝ විට එසේ විය හැකිය). ඒ නිසා, W වම් කකුල වේ lvalueහා glvalueහා දකුණු ගාතය වේ prvalueහා rvalue.මේ අතර, සෑම අගය එක්කෝ glvalue හෝ prvalue, නමුත් දෙකම ඇත.

මෙය ඉහළ මැදින් පිටවෙයි W: im; එනම්, අනන්‍යතාවය ඇති හා ගෙන යා හැකි අගයන්. එම අද්භූත තිරිසනුන් සඳහා හොඳ නමක් ලබා දෙන කිසිවක් අප සතුව නොමැත. (කෙටුම්පත්) සම්මත පා with ය සමඟ වැඩ කරන පුද්ගලයින්ට ඒවා වැදගත් වන නමුත් ගෘහස්ථ නමක් වීමට අපහසුය. අපට මඟ පෙන්වීම සඳහා නම් කිරීමේ කිසිදු සැබෑ බාධාවක් අපට හමු නොවීය, එබැවින් අපි කේන්ද්‍රය සඳහා 'x' තෝරා ගත්තෙමු, නොදන්නා, අමුතු, එක්ස්පර්ට් පමණක් හෝ එක්ස්-රේටඩ්.

ස්ටීව් අවසාන නිෂ්පාදනය පෙන්වයි


15
ඔව්, C ++ කොමිටියේ මුල් යෝජනා සහ සාකච්ඡා සම්මතයට වඩා කියවීම වඩා හොඳය, ඔවුන් අදහස් කළේ කුමක්ද යන්න ඔබට තේරුම් ගැනීමට අවශ්‍ය නම්: D
අයිවන් කුෂ්

8
සාහිත්‍යකරුවන්ට අනන්‍යතාවයක් නොමැති අතර එයින් ඉවත් විය නොහැක. ඒවා ප්‍රයෝජනවත් වුවත්.
DrPizza

මට අවශ්‍ය දෙයක් පැහැදිලි කර දීමටයි. int && f () {ආපසු 1; My සහ MyClass && g () {ආපසු MyClass (); x ආපසු xvalue නේද? එවිට ප්‍රකාශනවල අනන්‍යතාවය මට සොයාගත හැක්කේ f (); සහ "g ();"? ඔවුන්ට අනන්‍යතාවයක් ඇත, මන්ද ආපසු ප්‍රකාශයේ තවත් ප්‍රකාශනයක් ඇති අතර, එය ඔවුන් සඳහන් කරන එකම වස්තුවට යොමු දක්වයි - මට එය නිවැරදිව තේරෙනවාද?
ඩැනියෙල් සන්ඩෝර්

6
RDrPizza ප්‍රමිතියට අනුව: නූල් වචනාර්ථය lvalues වේ, අනෙක් සියලුම සාක්ෂරයන් prvalues වේ. නිශ්චිතවම කිවහොත්, නූල් නොවන වචනාර්ථය නිශ්චල විය යුතු යැයි පැවසීම සඳහා ඔබට තර්කයක් ඉදිරිපත් කළ හැකිය, නමුත් ප්‍රමිතිය ලියා ඇත්තේ එලෙස නොවේ.
බ්‍රයන් වැන්ඩන්බර්ග්

60

හැදින්වීම

ISOC ++ 11 (නිල වශයෙන් ISO / IEC 14882: 2011) යනු C ++ ක්‍රමලේඛන භාෂාවේ ප්‍රමිතියේ නවතම අනුවාදයයි. එහි නව විශේෂාංග සහ සංකල්ප අඩංගු වේ, උදාහරණයක් ලෙස:

  • rvalue යොමුව
  • xvalue, glvalue, prvalue ප්‍රකාශන අගය කාණ්ඩ
  • අර්ථකථන ගෙනයන්න

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

int& r_i=7; // compile error
int&& rr_i=7; // OK

වැඩ කරන කෙටුම්පත වන N3337 (ප්‍රකාශිත ISOC ++ 11 ප්‍රමිතියට වඩාත්ම සමාන කෙටුම්පත) වෙතින් Lvalues ​​සහ Rvalues ​​යන උපවගන්තිය උපුටා දැක්වුවහොත් අපට වටිනාකම් කාණ්ඩ පිළිබඳ සංකල්ප පිළිබඳ යම් අවබෝධයක් ලබා ගත හැකිය.

3.10 අගයන් සහ අගයන් [basic.lval]

රූප සටහන 1 හි වර්ගීකරනය අනුව ප්‍රකාශන වර්ගීකරණය කර ඇත.

  • Lvalue (පැවරුම් ප්‍රකාශනයක වම් පසින් lvalues ​​දිස්විය හැකි නිසා ically තිහාසිකව ඊනියා) ශ්‍රිතයක් හෝ වස්තුවක් නියම කරයි. . තවත් උදාහරණයක් ලෙස, ශ්‍රිතයක් ආපසු යැවීමේ වර්ගය lvalue යොමු කිරීමක් ලෙස හැඳින්වීමේ ප්‍රති result ලය lvalue වේ. උදාහරණයක් ලෙස]
  • Xvalue (“eXpiring” අගයක්) යනු සාමාන්‍යයෙන් වස්තුවක් එහි ආයු කාලය අවසන් වීමට ආසන්නය (උදාහරණයක් ලෙස එහි සම්පත් ගෙනයාමට). Xvalue යනු අගය යොමු කිරීම් (8.3.2) සම්බන්ධ වන ඇතැම් ප්‍රකාශනවල ප්‍රති result ලයකි. [උදාහරණය: ප්‍රතිලාභ වර්ගයක් වන අගය යොමු කිරීමක් වන ශ්‍රිතයක් ඇමතීමේ ප්‍රති x ලය xvalue වේ. උදාහරණයක් ලෙස]
  • ග්ලව් අගය (“සාමාන්‍යකරණය කරන ලද” අගය) යනු අගයක් හෝ xvalue වේ.
  • පැවරුම් ප්‍රකාශනයක දකුණු පසින් අගයන් දිස්විය හැකි බැවින්, අගයක් (ඊනියා, ically තිහාසිකව) යනු xvalue,
    තාවකාලික වස්තුවක් (12.2) හෝ එහි උප විෂය හෝ
    වස්තුවක් හා සම්බන්ධ නොවන අගයකි .
  • ප්‍රව්ලියු (“පිරිසිදු” අගය) යනු xvalue නොවන rvalue වේ. [උදාහරණය: නැවත පැමිණීමේ වර්ගය
    යොමු නොවන ශ්‍රිතයක් ඇමතීමේ ප්‍රති result ලය අගයක් වේ. 12, 7.3e5, හෝ
    සත්‍ය වැනි වචනාර්ථයක වටිනාකම ද අගයක් වේ . උදාහරණයක් ලෙස]

සෑම ප්‍රකාශනයක්ම මෙම වර්ගීකරණයේ මූලික වර්ගීකරණයන්ගෙන් එකකට අයත් වේ: lvalue, xvalue, හෝ prvalue. ප්‍රකාශනයක මෙම ගුණාංගය එහි අගය කාණ්ඩය ලෙස හැඳින්වේ.

නමුත් මෙම උපවගන්තිය සංකල්ප පැහැදිලිව වටහා ගැනීමට ප්‍රමාණවත් යැයි මට විශ්වාස නැත, මන්ද “සාමාන්‍යයෙන්” ඇත්ත වශයෙන්ම සාමාන්‍ය නොවන අතර, “එහි ජීවිත කාලය අවසන් වන විට” සැබවින්ම කොන්ක්‍රීට් නොවන අතර, “වටිනාකම් යොමු කිරීම් සම්බන්ධ” ඇත්ත වශයෙන්ම පැහැදිලි නැත, සහ "උදාහරණය: ප්‍රතිලාභ වර්ගයක් වන අගය යොමු කිරීමක් වන ශ්‍රිතයක් ඇමතීමේ ප්‍රති x ලය xvalue වේ." සර්පයෙක් වලිගය දෂ්ට කරනවා වගේ.

ප්‍රාථමික වටිනාකම් කාණ්ඩ

සෑම ප්‍රකාශනයක්ම හරියටම එක් ප්‍රාථමික අගය කාණ්ඩයකට අයත් වේ. මෙම අගය කාණ්ඩ වන්නේ lvalue, xvalue සහ prvalue කාණ්ඩ වේ.

lvalues

E යන ප්‍රකාශය lvalue ගණයට අයත් වන්නේ නම් සහ E යන්නෙන් දැනටමත් අනන්‍යතාවයක් (ලිපිනය, නම හෝ අන්වර්ථය) ඇති ආයතනයක් E ට පිටතින් ප්‍රවේශ විය හැකි නම් පමණි.

#include <iostream>

int i=7;

const int& f(){
    return i;
}

int main()
{
    std::cout<<&"www"<<std::endl; // The expression "www" in this row is an lvalue expression, because string literals are arrays and every array has an address.  

    i; // The expression i in this row is an lvalue expression, because it refers to the same entity ...
    i; // ... as the entity the expression i in this row refers to.

    int* p_i=new int(7);
    *p_i; // The expression *p_i in this row is an lvalue expression, because it refers to the same entity ...
    *p_i; // ... as the entity the expression *p_i in this row refers to.

    const int& r_I=7;
    r_I; // The expression r_I in this row is an lvalue expression, because it refers to the same entity ...
    r_I; // ... as the entity the expression r_I in this row refers to.

    f(); // The expression f() in this row is an lvalue expression, because it refers to the same entity ...
    i; // ... as the entity the expression f() in this row refers to.

    return 0;
}

xvalues

E ප්‍රකාශනය xvalue ගණයට අයත් වන්නේ නම් එය තිබේ නම් පමණි

- ශ්‍රිතයක් කැඳවීමේ ප්‍රති result ලය, ව්‍යංගයෙන් හෝ පැහැදිළිව, ආපසු පැමිණීමේ වර්ගය ආපසු ලබා දෙන වස්තු වර්ගය පිළිබඳ තක්සේරු කිරීමකි, හෝ

int&& f(){
    return 3;
}

int main()
{
    f(); // The expression f() belongs to the xvalue category, because f() return type is an rvalue reference to object type.

    return 0;
}

- වස්තු වර්ගයට තක්සේරු අගයකට යොමු කිරීම, හෝ

int main()
{
    static_cast<int&&>(7); // The expression static_cast<int&&>(7) belongs to the xvalue category, because it is a cast to an rvalue reference to object type.
    std::move(7); // std::move(7) is equivalent to static_cast<int&&>(7).

    return 0;
}

- වස්තු ප්‍රකාශනය xvalue එකක් වන, යොමු නොවන වර්ගයක ස්ථිතික නොවන දත්ත සාමාජිකයෙකු නම් කරන පන්ති සාමාජික ප්‍රවේශ ප්‍රකාශනය.

struct As
{
    int i;
};

As&& f(){
    return As();
}

int main()
{
    f().i; // The expression f().i belongs to the xvalue category, because As::i is a non-static data member of non-reference type, and the subexpression f() belongs to the xvlaue category.

    return 0;
}

- පළමු ඔපෙරන්ඩ් එක xvalue වන අතර දෙවන ඔපෙරන්ඩ් දත්ත සාමාජිකයාට දර්ශකයක් වන පොයින්ටර්-ට-සාමාජික ප්‍රකාශනයකි.

ඉහත නීතිරීතිවල බලපෑම නම්, වස්තූන් සඳහා නම් කරන ලද අගයන් යොමු කිරීම් අගයන් ලෙස සලකන අතර වස්තූන් සඳහා නම් නොකල තක්සේරු අගයන් xvalues ​​ලෙස සලකනු ලැබේ; ශ්‍රිත පිළිබඳ rvalue යොමුව නම් කළත් නැතත් lvalues ​​ලෙස සලකනු ලැබේ.

#include <functional>

struct As
{
    int i;
};

As&& f(){
    return As();
}

int main()
{
    f(); // The expression f() belongs to the xvalue category, because it refers to an unnamed rvalue reference to object.
    As&& rr_a=As();
    rr_a; // The expression rr_a belongs to the lvalue category, because it refers to a named rvalue reference to object.
    std::ref(f); // The expression std::ref(f) belongs to the lvalue category, because it refers to an rvalue reference to function.

    return 0;
}

prvalues

E යන ප්‍රකාශනය ප්‍රත්‍යාවර්ත ගණයට අයත් වන්නේ නම් සහ ඊ අගය අගයට හෝ xvalue කාණ්ඩයට අයත් නොවේ නම් පමණි.

struct As
{
    void f(){
        this; // The expression this is a prvalue expression. Note, that the expression this is not a variable.
    }
};

As f(){
    return As();
}

int main()
{
    f(); // The expression f() belongs to the prvalue category, because it belongs neither to the lvalue nor to the xvalue category.

    return 0;
}

මිශ්‍ර වටිනාකම් කාණ්ඩ

තවත් වැදගත් මිශ්‍ර වටිනාකම් කාණ්ඩ දෙකක් තිබේ. මෙම අගය කාණ්ඩ rvalue සහ glvalue කාණ්ඩ වේ.

rvalues

E ප්‍රකාශනය rvalue ගණයට අයත් වන්නේ නම් E අගය xvalue ගණයට අයත් වේ නම් හෝ ප්‍රාව්‍යතා කාණ්ඩයට පමණි.

මෙම අර්ථ දැක්වීමෙන් අදහස් වන්නේ E ප්‍රකාශනය Rvalue ගණයට අයත් වන්නේ නම් සහ E යන්නෙන් පිටත කිසිදු ප්‍රවේශයක් ලබා ගත හැකි කිසිදු අනන්‍යතාවයක් නොමැති වස්තුවක් E යන්නෙන් අදහස් කරන්නේ නම් පමණි.

glvalues

E ප්‍රකාශනය ග්ලැවල් අගය ගණයට අයත් වන්නේ නම් සහ ඊ අගය lvalue ගණයට අයත් නම් හෝ xvalue කාණ්ඩයට අයත් වේ.

ප්‍රායෝගික නීතියක්

ස්කොට් මේයර් විසින් අගයන් අගයන්ගෙන් වෙන්කර හඳුනා ගැනීම සඳහා ඉතා ප්‍රයෝජනවත් රීතියක් ප්‍රකාශයට පත් කර ඇත .

  • ඔබට ප්‍රකාශනයක ලිපිනය ගත හැකි නම්, ප්‍රකාශනය අගයකි.
  • ප්‍රකාශනයේ වර්ගය lvalue යොමු කිරීමක් නම් (උදා: T & හෝ const T &, ආදිය), එම ප්‍රකාශනය අගයක් වේ.
  • එසේ නොමැති නම් ප්‍රකාශනය අගයකි. සංකල්පමය වශයෙන් (සහ සාමාන්‍යයෙන් ඇත්ත වශයෙන්ම), අගයන් තාවකාලික වස්තූන් වලට අනුරූප වේ. බොහෝ වචනාර්ථ අගයන් (උදා: 10 සහ 5.3) ද අගයන් වේ.

3
Lvalues ​​සඳහා වන සියලුම උදාහරණ සහ xvalues ​​සඳහා වන සියලුම උදාහරණ glvalues ​​සඳහා උදාහරණ වේ. සංස්කරණය කිරීමට ස්තූතියි!
ඩැනියෙල් සන්ඩෝර්

1
ඔයා හරි. ප්‍රාථමික අගය කාණ්ඩ තුන ප්‍රමාණවත් වේ. අගය ද අවශ්‍ය නොවේ. මම හිතන්නේ rvalue සහ glvalue පහසුව සඳහා ප්‍රමිතියේ ඇත.
ඩැනියෙල් සන්ඩෝර්

1
ඇති තේරුම් ගැනීමට අපහසු struct As{void f(){this;}}වන thisවිචල්ය වන prvalue වේ. මම හිතුවේ thisලාලියක් වෙන්න ඕනේ. සම්මත 9.3.2 පවසන තුරු: ස්ථිතික නොවන (9.3) සාමාජික ශ්‍රිතයක, මෙය මූලික පදය ප්‍රත්‍යක්‍ෂ ප්‍රකාශනයකි.
r0ng

3
0 r0ng thisයනු අගයක් වන නමුත් *thisඑය අගයක් වේ
Xeverous

1
"www" සෑම විටම එකම ලිපිනය නොමැත. එය අරාවයක් බැවින් එය අගයක් වේ .
වොලී

35

ප්‍රකාශන ගුණාංගවලට නිවැරදිව අගය යොමු කිරීම ග්‍රහණය කර ගැනීමට C ++ 03 හි කාණ්ඩ සීමා කර ඇත.

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

මෙය පෙන්වීමට සලකා බලන්න

int const&& f();

int main() {
  int &&i = f(); // disgusting!
}

පූර්ව xvalue කෙටුම්පත් වලදී, මෙය අවසර දෙන ලදි, මන්ද C ++ 03 හි, පංති නොවන වර්ගවල අගයන් කිසි විටෙකත් cv- සුදුසුකම් නොලබයි. නමුත් එය බව අදහස් constමෙතන අපි නිසා, rvalue-යොමු නඩුවේ අදාළ නැහැ වස්තූන් වෙත යොමු වන්න (= මතක!), හා පන්ති නොවන rvalues සිට const පහත වැටේ කිසිදු වස්තුවක් වටා පවතින බව හේතුව සඳහා ප්රධාන වශයෙන් වේ.

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

  • නම් නොකළ rvalue යොමු කිරීම් xvalues ​​බවට පත්වේ . ඔවුන් සුදුසුකම් ලැබිය හැකි අතර ඒවායේ ගතික වර්ගය වෙනස් විය හැකිය. ඔවුන් බලාපොරොත්තු වන පරිදි, අධික බර පැටවීමේදී අගය යොමු කිරීම් වලට වැඩි කැමැත්තක් දක්වන අතර, නියත නොවන අගයන් යොමු කිරීම් සමඟ බැඳී නොසිටිනු ඇත.

  • කලින් අගය කළ දෙය (වචනානුසාරයෙන්, යොමු නොවන වර්ග වලට කැස්ට් විසින් නිර්මාණය කරන ලද වස්තූන්) දැන් අගයක් බවට පත්වේ . අධි බර පැටවීමේදී xvalues ​​වලට සමාන මනාපයක් ඔවුන් සතුව ඇත.

  • මීට පෙර lvalue එකක් යනු අගයක් වේ.

කණ්ඩායම් දෙකක් සිදු කරනුයේ සුදුසුකම් ලැබිය හැකි සහ විවිධ ගතික වර්ග ( ග්ලැවල් ) තිබිය හැකි සහ අධික ලෙස පැටවීම මඟින් අගය යොමු බන්ධන ( අගයන් ) ලබා ගැනීමට ය.


1
පිළිතුර පැහැදිලිවම සාධාරණ ය. xvalue යනු cv- සුදුසුකම් සහ ගතික ටයිප් කළ හැකි rvalue පමණි!
ලිගන්ඩ්

26

වටිනාකම් කාණ්ඩ පිළිබඳ cppreference.com පැහැදිලි කිරීම මට ලැබෙන තෙක් මම දීර් with කාලයක් තිස්සේ මේ සමඟ පොරබදිමි .

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

ප්‍රාථමික කාණ්ඩ

ප්‍රාථමික අගය කාණ්ඩ ප්‍රකාශනවල ගුණාංග දෙකකට අනුරූප වේ:

  • අනන්‍යතාවයක් ඇත : ප්‍රකාශනය වෙනත් ප්‍රකාශනයක් ලෙස එකම වස්තුවට යොමු කරන්නේද යන්න තීරණය කළ හැකිය, එනම් වස්තූන්ගේ ලිපින හෝ ඒවා හඳුනා ගන්නා කාර්යයන් සංසන්දනය කිරීමෙන් (සෘජුව හෝ වක්‍රව ලබා ගත්);

  • සිට ගෙන යා හැකිය : චලනය වන ඉදිකිරීම්කරු, චලන පැවරුම් ක්‍රියාකරු හෝ චලනය වන අර්ථකථන ක්‍රියාත්මක කරන වෙනත් ශ්‍රිත අධි බරක් ප්‍රකාශනයට බැඳිය හැකිය.

ප්‍රකාශන:

  • අනන්‍යතාවයක් ඇති අතර එයින් ඉවත් කළ නොහැකි ඒවා lvalue ප්‍රකාශන ලෙස හැඳින්වේ ;
  • අනන්‍යතාවයක් ඇති අතර එයින් ගෙන යා හැකි xvalue ප්‍රකාශන ලෙස හැඳින්වේ ;
  • අනන්‍යතාවයක් නොමැති අතර ඒවායින් ඉවත් කළ හැකිය prvalue ප්‍රකාශන ලෙස හැඳින්වේ ;
  • අනන්‍යතාවයක් නොමැති අතර එයින් ඉවත් කළ නොහැක.

lvalue

Lvalue ("වම් අගය") ප්‍රකාශනය යනු අනන්‍යතාවය ඇති අතර එයින් ගෙන යා නොහැකි ප්‍රකාශනයකි .

rvalue (C ++ 11 දක්වා), prvalue (C ++ 11 සිට)

ඒ prvalue ( "පිරිසිදු rvalue") ප්රකාශනය බව ප්රකාශනයකි අනන්යතාව නැති සහ චුන්ඩිකුලම් සිට කළ හැකි .

xvalue

ක xvalue ( "යුද වැදුණු අගය") ප්රකාශනය බව ප්රකාශනයකි අනන්යතාව ඇති හා පදිංචියට ගියා ගත හැක .

glvalue

ග්ලව් අගය ("සාමාන්‍යකරණය කරන ලද අගයන්") ප්‍රකාශනය යනු අගයක් හෝ xvalue එකක් වන ප්‍රකාශනයකි. එයට අනන්‍යතාවයක් ඇත. එය ගෙනයාමට හෝ නොවීමට ඉඩ ඇත.

rvalue (C ++ 11 සිට)

Rvalue ("නිවැරදි අගය") ප්‍රකාශනය යනු ප්‍රත්‍යක්‍ෂයක් හෝ xvalue එකක් වන ප්‍රකාශනයකි. එය ගෙන යා හැකිය . එයට අනන්‍යතාවයක් තිබිය හැකිය හෝ නොතිබිය හැකිය.


1
සමහර පොත්වල xvalues ​​ඔවුන්ගේ x පැමිණියේ “විශේෂ expert” හෝ “සුවිශේෂී”
අයගෙන් බව පෙන්වයි

වැදගත්ම දෙය නම්, ඔවුන්ගේ සර්ව සම්පූර්ණ උදාහරණ ලැයිස්තුවයි.
සිරෝ සැන්ටිලි 郝海东 冠状 病 六四 事件 法轮功

19

මෙම නව කාණ්ඩයන් දැනට පවතින අගය හා lvalue කාණ්ඩ සමඟ සම්බන්ධ වන්නේ කෙසේද?

C ++ 03 lvalue තවමත් C ++ 11 lvalue වන අතර C ++ 03 rvalue එකක් C ++ 11 හි prvalue ලෙස හැඳින්වේ.


14

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

int&& a = 3,

එය int&&වර්ගයක් ලෙස කියවා aඑය අගයක් ලෙස නිගමනය කිරීම ඉතා පෙළඹවීමකි. එය නෙමෙයි:

int&& a = 3;
int&& c = a; //error: cannot bind 'int' lvalue to 'int&&'
int& b = a; //compiles

aනමක් ඇති අතර එය සත්‍ය අගයකි. &&වර්ගයෙහි කොටසක් ලෙස නොසිතන්න a; එය aබැඳීමට ඉඩ දී ඇති දේ ඔබට පවසන දෙයක් පමණි .

මෙය විශේෂයෙන් T&&ඉදිකිරීම්කරුවන්ගේ වර්ග තර්ක සඳහා වැදගත් වේ. ඔබ ලියන්නේ නම්

Foo::Foo(T&& _t) : t{_t} {}

ඔබ පිටපත් _tකරනු ඇත t. ඔබට අවශ්යයි

Foo::Foo(T&& _t) : t{std::move(_t)} {}ඔබට ගමන් කිරීමට අවශ්‍ය නම්. මම පිටව ගිය විට මගේ සම්පාදකයා මට අනතුරු ඇඟවූවා නම් move!


1
මෙම පිළිතුර පැහැදිලි කළ හැකි යැයි මම සිතමි. " aබැඳීමට අවසර දී ඇත්තේ කුමක්ද ": ෂුවර්, නමුත් 2 සහ 3 පේළියේ ඔබේ විචල්‍යයන් සී ඇන්ඩ් බී වන අතර එය බැඳී ඇති aදෙයක් නොවන අතර මෙහි වර්ගය අදාල නොවේ. aප්‍රකාශ කළහොත් රේඛා සමාන int aවේ. මෙහි ඇති සැබෑ ප්‍රධාන වෙනස නම් 1 වන පේළියේ 3 ට constබැඳිය යුතු නැත.
ෆීලික්ස් ඩොම්බෙක්

12

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

වටිනාකම් කාණ්ඩ සමඟ අත්හදා බැලීම් සඳහා, ඔබට ඩෙක්ටයිප් පිරිවිතර භාවිතා කළ හැකිය . එහි හැසිරීම ප්‍රාථමික අගය කාණ්ඩ තුන (xvalue, lvalue සහ prvalue) අතර පැහැදිලිව වෙන්කර හඳුනා ගනී.

පෙර සැකසුම් යන්ත්‍රය භාවිතා කිරීමෙන් අපට යතුරු ලියනය කිරීම ඉතිරි වේ ...

ප්‍රාථමික කාණ්ඩ:

#define IS_XVALUE(X) std::is_rvalue_reference<decltype((X))>::value
#define IS_LVALUE(X) std::is_lvalue_reference<decltype((X))>::value
#define IS_PRVALUE(X) !std::is_reference<decltype((X))>::value

මිශ්‍ර කාණ්ඩ:

#define IS_GLVALUE(X) (IS_LVALUE(X) || IS_XVALUE(X))
#define IS_RVALUE(X) (IS_PRVALUE(X) || IS_XVALUE(X))

දැන් අපට වටිනාකම් කාණ්ඩය පිළිබඳ cppreference වෙතින් සියලු උදාහරණ (පාහේ) ප්‍රතිනිෂ්පාදනය කළ හැකිය .

C ++ 17 සමඟ උදාහරණ කිහිපයක් මෙන්න (terse static_assert සඳහා):

void doesNothing(){}
struct S
{
    int x{0};
};
int x = 1;
int y = 2;
S s;

static_assert(IS_LVALUE(x));
static_assert(IS_LVALUE(x+=y));
static_assert(IS_LVALUE("Hello world!"));
static_assert(IS_LVALUE(++x));

static_assert(IS_PRVALUE(1));
static_assert(IS_PRVALUE(x++));
static_assert(IS_PRVALUE(static_cast<double>(x)));
static_assert(IS_PRVALUE(std::string{}));
static_assert(IS_PRVALUE(throw std::exception()));
static_assert(IS_PRVALUE(doesNothing()));

static_assert(IS_XVALUE(std::move(s)));
// The next one doesn't work in gcc 8.2 but in gcc 9.1. Clang 7.0.0 and msvc 19.16 are doing fine.
static_assert(IS_XVALUE(S().x)); 

ඔබ ප්‍රාථමික කාණ්ඩය හදුනාගත් පසු මිශ්‍ර කාණ්ඩ නීරස වේ.

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


1
මම හිතන්නේ #define IS_GLVALUE(X) IS_LVALUE(X) || IS_XVALUE(X)ඇත්ත වශයෙන්ම #define IS_GLVALUE(X) (IS_LVALUE(X) || IS_XVALUE(X))ඔබ &&දෙදෙනා නම් කුමක් සිදුවේද යන්න සොයා බැලිය යුතුය IS_GLVALUE.
ගේබ්‍රියෙල් ඩෙවිලර්ස්
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.