ãã®ãããã¯ã¯ãŸã Habréã§åãäžããããŠããŸãããããã®èšäºã¯ã³ãã¥ããã£ã«ãšã£ãŠèå³æ·±ããã®ã«ãªããšæããŸãã
å ã®èšäºïŒ ãC ++ 11ã®ãŠãããŒãµã«ãªãã¡ã¬ã³ã¹â Scott Meyersã
C ++ 11ã®ãŠãããŒãµã«ãªã³ã¯
T &&ã¯åžžã«ãRvalue Referenceããæå³ããããã§ã¯ãããŸãã
æçš¿è ïŒ Scott Meyers
ãããããC ++ 11ã§æãéèŠãªé©æ°ã¯å³èŸºå€ãªã³ã¯ã§ãã ãããã¯ãã転éã®ã»ãã³ãã£ã¯ã¹ïŒè±èªã®ç§»åã»ãã³ãã£ã¯ã¹ïŒãããã³ãå®å šãªè»¢éããæ§ç¯ãããåºç€ãšããŠæ©èœããŸãã ïŒ Thomas Beckerã®ã¬ãã¥ãŒã§ããããã®ã¡ã«ããºã ã®åºæ¬ã«æ £ããããšãã§ããŸã ïŒã
æ§æçã«å³èŸºå€ãªã³ã¯ã¯ããéåžžã®ããªã³ã¯ïŒçŸåšå·ŠèŸºå€ãªã³ã¯ãšåŒã°ããïŒãšåãæ¹æ³ã§å®£èšãããŸããã1ã€ã§ã¯ãªã2ã€ã®ã¢ã³ããµã³ãã䜿çšããŸãã ãããã£ãŠããã®é¢æ°ã¯ãrvalue-reference-to-Widgetåã®ãã©ã¡ãŒã¿ãŒãåãå ¥ããŸãã
void f(Widget&& param);
å³èŸºå€åç §ã&&ã䜿çšããŠå®£èšãããŠããããšãèãããšãå宣èšå ã®&&ã®ååšãå³èŸºå€åç §ã瀺ããŠãããšä»®å®ããã®ã¯åççã§ãã ããããããã¯ããã§ã¯ãããŸããïŒ
Widget&& var1 = someWidget; // â&&â rvalue auto&& var2 = var1; // â&&â rvalue template<typename T> void f(std::vector<T>&& param); // â&&â rvalue template<typename T> void f(T&& param); // â&&â rvalue
ãã®èšäºã§ã¯ãå宣èšã®2ã€ã®ã&&ãã®æå³ã説æããããããäºãã«åºå¥ããæ¹æ³ã説æãã䜿çšããã&&ãå€ãæ確ã«æ±ºå®ã§ããæ°ããçšèªã玹ä»ããŸãã å宣èšã«ã&&ãã衚瀺ãããŠãããšãã«ãå³èŸºå€ãªã³ã¯ãã«ã€ããŠèãããšã倧éã®C ++ 11ã³ãŒãã誀解ãããããç°ãªãå€ã匷調衚瀺ããããšãéèŠã§ãã
ãã€ã³ãã¯ãå宣èšã®&&ã¯å³èŸºå€ãªã³ã¯ãæå³ããããšã§ãããå³èŸºå€ãªã³ã¯ãŸãã¯å·ŠèŸºå€ãªã³ã¯ã®ãããããæå³ããå ŽåããããŸãã ãããã£ãŠãå Žåã«ãã£ãŠã¯ããœãŒã¹ã³ãŒãã®ã&&ãã®å€ããïŒããã€ãŸã æ§æçã«ã¯å³èŸºå€åç §ïŒã&&ãïŒã®åœ¢åŒã§ãããå®éã«ã¯å·ŠèŸºå€åç §ïŒãïŒãïŒã«ãªããŸãã
ãªã³ã¯ã¯ã巊蟺å€ãªã³ã¯ãŸãã¯å³èŸºå€ãªã³ã¯ãããæè»ãªæŠå¿µã§ãã ãããã£ãŠãå³èŸºå€ãªã³ã¯ã¯å³èŸºå€ã«ã®ã¿é¢é£ä»ããããšãã§ãã巊蟺å€ãªã³ã¯ã¯å·ŠèŸºå€ã«ãã€ã³ãã§ããããšã«å ããŠãéãããæ¡ä»¶äžã§å³èŸºå€ã«é¢é£ä»ããããšãã§ããŸãïŒå·ŠèŸºå€ãªã³ã¯ãšå³èŸºå€ã®ãªã³ã¯ã®å¶éã¯ããã®ãããªãªã³ã¯ãèš±å¯ãããã®ã¯ã巊蟺å€ãªã³ã¯ã¯ãå®æ°ãã€ãŸãconst TïŒãžã®åç §ãšããŠå®£èšãããŸãã巊蟺å€ãªã³ã¯ãŸãã¯å³èŸºå€ãªã³ã¯ã®ããããã§ãã&&ã§å®£èšããããªã³ã¯ã¯ããããããã®ã«æ¥ç¶ã§ããŸãã ãã®ãããªéåžžã«æè»ãªãªã³ã¯ã¯ããã®ååã«å€ããŸãã ç§ã¯ããããããŠãããŒãµã«ããªã³ã¯ãšåŒã³ãŸããã
ã&&ããæ®éçãªåç §ãæå³ããå ŽåïŒã€ãŸãããœãŒã¹ã³ãŒãã®ã&&ããå®éã«ãïŒããæå³ããå ŽåïŒã®è©³çŽ°ã¯éåžžã«è€éã§ããããã説æãå éãããŸãã ããŠã次ã®ã«ãŒã«ã«çŠç¹ãåœãŠãŸããããããã¯ãæ¯æ¥ããã°ã©ãã³ã°ãããšãã«èŠããŠããã¹ãããšã§ãã
æšå®ãããå Tã«å¯ŸããŠåT &&ã§å€æ°ãŸãã¯ãã©ã¡ãŒã¿ãŒã宣èšãããŠããå Žåããã®ãããªå€æ°ãŸãã¯ãã©ã¡ãŒã¿ãŒã¯æ±çšåç §ã§ãã
åæšè«ã®èŠä»¶ã«ãããæ®éçãªåç §ãããç¶æ³ã®ç¯å²ãå¶éãããŸãã ã»ãšãã©ãã¹ãŠã®æ±çšåç §ã¯ãé¢æ°ãã³ãã¬ãŒãã®ãã©ã¡ãŒã¿ãŒã§ãã ãŸããèªå宣èšãããå€æ°ã®åæšè«èŠåã¯ãã³ãã¬ãŒãã®å Žåãšåºæ¬çã«åãã§ãããããèªå宣èšããããŠãããŒãµã«åç §ãå¯èœã§ãã ãããã¯æ¬çªã³ãŒãã§ã¯ããŸãèŠãããŸãããããã³ãã¬ãŒãã®åé·ãªäŸã§ã¯ãªãããããã®èšäºã§ã¯ãã®äžéšã玹ä»ããŸãã ãã®èšäºã®ãã¹ã¢ãŒã«ãã£ããŒã«ãã»ã¯ã·ã§ã³ã§ã¯ãtypedefããã³decltypeã®äœ¿çšã«é¢é£ãããŠãããŒãµã«ãªã³ã¯ã®å¯èœæ§ã瀺ããŸããããã¹ã¢ãŒã«ãã£ããŒã«ãã«å°éãããŸã§ããŠãããŒãµã«ãªã³ã¯ã¯é¢æ°ãã³ãã¬ãŒããšèªåãªã³ã¯ã®ã¿ãåç §ãããšæ³å®ããŸãã宣èšãããå€æ°ã
T &&ãŠãããŒãµã«ãªã³ã¯å®£èšãã©ãŒã ã¯ãèŠãããããéèŠãªèŠä»¶ã§ãããåŸã§ãã®åé¡ã«æ»ããŸãã ãããŸã§ã®éããã®èŠä»¶ã念é ã«çœ®ããŠãã ããã
ãã¹ãŠã®ãªã³ã¯ãšåæ§ã«ããŠãããŒãµã«ãªã³ã¯ã¯åæåããå¿ èŠããããããã巊蟺å€ãªã³ã¯ãšå³èŸºå€ãªã³ã¯ã®ã©ã¡ãã§ãããã決å®ããã®ã¯ãŠãããŒãµã«ãªã³ã¯ã€ãã·ã£ã©ã€ã¶ãŒã§ãã
- ãŠãããŒãµã«åç §ãåæåããåŒã巊蟺å€ã§ããå ŽåããŠãããŒãµã«åç §ã¯å·ŠèŸºå€åç §ã«ãªããŸãã
- ãŠãããŒãµã«åç §ãåæåããåŒãå³èŸºå€ã§ããå ŽåããŠãããŒãµã«åç §ã¯å³èŸºå€åç §ã«ãªããŸãã
ãã®æ å ±ã¯ã巊蟺å€ãšå³èŸºå€ãåºå¥ã§ããå Žåã«ã®ã¿åœ¹ç«ã¡ãŸãã ãããã®çšèªãæ£ç¢ºã«å®çŸ©ããããšã¯å°é£ã§ãïŒC ++ 11æšæºã§ã¯ãåŒã巊蟺å€ã§ãããå³èŸºå€ã§ãããã¯äžè¬çã«å®çŸ©ãããŠããŸãïŒããå®éã«ã¯ä»¥äžã§ååã§ãã
- åŒã®ã¢ãã¬ã¹ãååŸã§ããå Žåããã®åŒã¯å·ŠèŸºå€ã§ãã
- åŒã®åã巊蟺å€åç §ïŒã€ãŸããTïŒãŸãã¯const TïŒãªã©ïŒã§ããå Žåããã®åŒã¯å·ŠèŸºå€ã§ãã
- ãã以å€ã®å ŽåãåŒã¯å³èŸºå€ã§ãã æŠå¿µçã«ïŒãããŠéåžžãå®éïŒãå³èŸºå€ã¯ãé¢æ°ããè¿ããããªããžã§ã¯ããæé»çãªåå€æã«ãã£ãŠäœæããããªããžã§ã¯ããªã©ã®äžæãªããžã§ã¯ãã«å¯Ÿå¿ããŸãã ã»ãšãã©ã®ãªãã©ã«ïŒ10ã5.3ãªã©ïŒãå³èŸºå€ã§ãã
èšäºã®åé ã®ã³ãŒããããäžåºŠèŠãŠã¿ãŸãããã
Widget&& var1 = someWidget; auto&& var2 = var1;
ã¢ãã¬ã¹var1ãååŸã§ããŸããããããvar1ã¯å·ŠèŸºå€ã§ãã var2ãauto &&ãšããŠå®£èšãããšãvar2ã¯æ±çšåç §ã«ãªããvar1ïŒlvalueïŒã«ãã£ãŠåæåããããããvar2ã¯å·ŠèŸºå€åç §ã«ãªããŸãã
ãœãŒã¹ã³ãŒããäžæ³šæã«èªããšãvar2ãå³èŸºå€åç §ã§ãããšæãããå¯èœæ§ããããŸãã ãã¡ãããåºåã®ã&&ãã¯ãã®èãã«ã€ãªãããŸãã ãã ããvar2ã¯å·ŠèŸºå€ã«ãã£ãŠåæåãããæ±çšåç §ã§ããããã巊蟺å€åç §ã§ãã var2ã次ã®ããã«å®£èšãããŠããããã§ãã
Widget& var2 = var1;
äžèšã®ããã«ãåŒããªã³ã¯ã®å·ŠèŸºå€åã§ããå Žåãããã¯å·ŠèŸºå€ã§ãã ãã®äŸãèããŠã¿ãŸãããïŒ
std::vector<int> v; ... auto&& val = v[0]; // val lvalue (. )
valã¯æ±çšåç §ã§ãããåæåãããv [0]ã§ããã€ãŸãã std :: vector <int> :: operator []ãåŒã³åºããçµæã ãã®é¢æ°ã¯ããã¯ãã«èŠçŽ ãžã®å·ŠèŸºå€åç §ãè¿ããŸãïŒé åãè¶ ããããšã¯ç¡èŠããŸãããããã¯æªå®çŸ©ã®åäœã«ã€ãªãããŸãïŒã
ãã¹ãŠã®å·ŠèŸºå€åç §ã¯å·ŠèŸºå€ã§ããããã®å·ŠèŸºå€ã¯valã®åæåã«äœ¿çšããããããvalå宣èšã¯å³èŸºå€åç §ã®ããã«èŠããŸãããvalã¯å·ŠèŸºå€åç §ã«ãªããŸãã
ãŠãããŒãµã«ãªã³ã¯ã¯ãé¢æ°ãã³ãã¬ãŒããã©ã¡ãŒã¿ãŒã§æãäžè¬çã§ããããšã«æ³šæããŸããã ãã®èšäºã®æåãããã³ãã¬ãŒããå床æ€èšããŠãã ããã
template<typename T> void f(T&& param); // â&&â rvalue
ãã®ãããªåŒã³åºãfã§ã¯ã
f(10); // 10 rvalue
paramã¯ãªãã©ã«10ã§åæåãããŸããããã¯ãã¢ãã¬ã¹ãååŸã§ããªããšããçç±ã§å³èŸºå€ã§ãã ããã¯ãfã®åŒã³åºãã§ãæ±çšãã©ã¡ãŒã¿ãŒåç §ãå³èŸºå€ã«åæåããããããã£ãŠå³èŸºå€åç §ã«ãªãããšãæå³ããŸããå ·äœçã«ã¯ãint &&ã§ãã
äžæ¹ãfã次ã®ããã«åŒã³åºãããå ŽåïŒ
int x = 10; f(x); // x lvalue
paramã¯å€æ°xã«åæåãããŸããããã¯ãã¢ãã¬ã¹ãååŸã§ãããšããçç±ã§å·ŠèŸºå€ã§ãã ã€ãŸãããã®fã®åŒã³åºãã§ã¯ããŠãããŒãµã«paramåç §ã巊蟺å€ã«åæåããããããã£ãŠparamã¯æ£ç¢ºã«ã¯-intïŒãžã®å·ŠèŸºå€åç §ã«ãªããŸãã
fã®å®£èšã®æšªã«ããã³ã¡ã³ãã¯æ確ã«ãªããŸãããparamåã巊蟺å€åç §ã§ãããå³èŸºå€åç §ã§ãããã¯ãåŒã³åºãäžã«fã«æž¡ããããã®ã«äŸåããŸãã paramã¯å·ŠèŸºå€åç §ã«ãªãããšãããã°ãå³èŸºå€åç §ã«ãªãããšããããŸãã ã€ãŸããparamã¯ç¢ºãã«æ®éçãªåç §ã§ãã
&&ã¯ãåæšè«ãè¡ãããå Žåã«ã®ã¿ãŠãããŒãµã«åç §ã瀺ãããšã«æ³šæããŠãã ããã åã®æšè«ããªãå Žåãæ®éçãªåç §ã¯ãããŸããã ãã®ãããªå Žåãå宣èšã®ã&&ãã¯åžžã«å³èŸºå€åç §ãæå³ããŸãã ãããã£ãŠïŒ
template<typename T> void f(T&& param); // â ; && â¡ template<typename T> class Widget { ... Widget(Widget&& rhs); // â ; ... // && â¡ rvalue }; template<typename T1> class Gadget { ... template<typename T2> Gadget(T2&& rhs); // â ; && â¡ }; void f(Widget&& param); // â ; // && â¡ rvalue
ãããã®äŸã«ã¯é©ãã¹ãããšã¯äœããããŸããã ãããã«ãããT &&ïŒTã¯ãã³ãã¬ãŒããã©ã¡ãŒã¿ãŒïŒã衚瀺ãããå Žåãåæšè«ãååšããããããŠãããŒãµã«ãªã³ã¯ãèŠãŠããŸãã ãŸããç¹å®ã®ã¿ã€ãåïŒããšãã°ãWidget &&ïŒã®åŸã«ã&&ãã衚瀺ãããŠããå Žåã¯ãå³èŸºå€ãªã³ã¯ã確èªããŸãã
ãªã³ã¯ããŠãããŒãµã«ã«ããããã«ã¯ããªã³ã¯å®£èšãã©ãŒã ã¯ãT &&ãã§ããå¿ èŠããããšè¿°ã¹ãŸããã ããã¯éèŠãªãã¥ã¢ã³ã¹ã§ãã ãã®èšäºã®åé ã®å®£èšãããäžåºŠèŠãŠãã ããã
template<typename T> void f(std::vector<T>&& param); // â&&â rvalue
ããã«ã¯åæšè«ãšã&&ãã®äž¡æ¹ããããŸã-説æãããŠããé¢æ°ãã©ã¡ãŒã¿ãŒã§ããããã©ã¡ãŒã¿ãŒã®å®£èšåœ¢åŒã¯ãT &&ãã§ã¯ãªããstd :: vector <T> &&ãã§ãã ãã®çµæããã©ã¡ãŒã¿ãŒã¯éåžžã®å³èŸºå€åç §ã§ãããæ±çšåç §ã§ã¯ãããŸããã ãŠãããŒãµã«ãªã³ã¯å®£èšã¯ããT &&ãã®åœ¢åŒã§ã®ã¿äœ¿çšã§ããŸãã const修食åãè¿œå ããŠããã&&ããæ®éçãªåç §ãšããŠè§£éããªãããã«ã¯ååã§ãã
template<typename T> void f(const T&& param); // â&&â rvalue
ãT &&ãã¯ããŠãããŒãµã«ãªã³ã¯ã宣èšããããã«å¿ èŠãªåœ¢åŒã§ãã ããã¯ããã³ãã¬ãŒããã©ã¡ãŒã¿ã«ååTã䜿çšããå¿ èŠããããšããæå³ã§ã¯ãããŸããã
template<typename MyTemplateParamType> void f(MyTemplateParamType&& param); // â&&â
ãã³ãã¬ãŒãé¢æ°å®£èšã§T &&ã確èªã§ããå ŽåããããŸããTã¯ãã³ãã¬ãŒããã©ã¡ãŒã¿ãŒã§ãããåæšè«ã¯ãŸã ãããŸããã std :: vectorã®push_backé¢æ°ãæ€èšããŠãã ããïŒå¯Ÿè±¡ã®ããŒãžã§ã³ã®ã¿ã衚瀺ãããŸã
std::vector::push_back): template <class T, class Allocator = allocator<T> > class vector { public: ... void push_back(T&& x); // â ; ... // && â¡ rvalue };
ããã§ãTã¯ãã³ãã¬ãŒããã©ã¡ãŒã¿ãŒã§ãããpush_backã¯T &&ãåãå ¥ããŸãã ãã ãããã©ã¡ãŒã¿ãŒã¯æ®éçãªåç §ã§ã¯ãããŸããïŒ ããã¯ã©ã®ããã«ã§ããŸããïŒ
push_backãã¯ã©ã¹å€ã§ã©ã®ããã«å®£èšãããããèŠããšãçããæããã«ãªããŸãã ã³ãŒããä¹±éã«ããªãããã«ãAllocatorãã©ã¡ãŒã¿ãŒãæ¬ èœããŠãããµããããŸãã ãããèãããšã以äžã¯ãã®ããŒãžã§ã³ã®å®£èšã§ã
std ::ãã¯ãã«:: push_backïŒ
template <class T> void vector<T>::push_back(T&& x);
push_backã¯ãstd :: vector <T>ã¯ã©ã¹ãªãã§ã¯ååšã§ããŸããã ããããã¯ã©ã¹std :: vector <T>ãããå ŽåãTãäœã§ãããã¯æ¢ã«ããã£ãŠããããããã®åãæšæž¬ããå¿ èŠã¯ãããŸããã
äŸãèŠãŠã¿ãŸãããã æžããã
Widget makeWidget(); // Widget std::vector<Widget> vw; ... Widget w; vw.push_back(makeWidget()); // Widget vw
push_packã䜿çšãããšãstd :: vector <Widget>ã¯ã©ã¹ã«å¯ŸããŠãã®é¢æ°ãã€ã³ã¹ã¿ã³ã¹åããããã³ã³ãã€ã©ãŒã«æ瀺ããŸãã ã¯ã©ã¹å€ã§ã®åœŒå¥³ã®å®£èšã¯æ¬¡ã®ããã«ãªããŸãã
void std::vector<Widget>::push_back(Widget&& x);
åãããŸããïŒ ã¯ã©ã¹ãstd :: vector <Widget>ã§ããããšãããããšããã«ãpush_backãã©ã¡ãŒã¿ãŒã®ã¿ã€ããå®å šã«å®çŸ©ãããŸãã åæšè«ã¯å®è¡ãããŸããã
ãããã次ã®ããã«å®£èšãããŠããemplace_back std :: vectorã¡ãœãããšæ¯èŒããŸãã
template <class T, class Allocator = allocator<T> > class vector { public: ... template <class... Args> void emplace_back(Args&&... args); // â ; ... // && â¡ };
emplace_backãå¯å€æ°ã®åŒæ°ãåãå ¥ãããšããäºå®ã«æ³šæãæããªãã§ãã ããïŒArgsããã³args宣èšã§ç€ºãããŠããããã«ïŒã ããã§éèŠãªã®ã¯ãååŒæ°ã®åãæšæž¬ããå¿ èŠããããšããããšã§ãã Argsé¢æ°ã®ãã³ãã¬ãŒããã©ã¡ãŒã¿ãŒã¯ãã¯ã©ã¹Tã®ãã³ãã¬ãŒããã©ã¡ãŒã¿ãŒãšã¯ç¡é¢ä¿ã§ãããã®ãããã¯ã©ã¹ãå®å šã«ããã£ãŠããå ŽåïŒstd :: vector <Widget>ãªã©ïŒã§ããemplace_backåŒæ°ã®ã¿ã€ãã«ã€ããŠã¯äœãèšããŸããã std :: vector <Widget>ã®ã¯ã©ã¹å€ã®emplace_back宣èšã¯ããããæ確ã«ç€ºããŠããŸãïŒAllocatorãã©ã¡ãŒã¿ãŒã®ååšã¯ç¡èŠãç¶ããŠããŸãïŒã
template<class... Args> void std::vector<Widget>::emplace_back(Args&&... args);
æããã«ãã¯ã©ã¹ãstd :: vector <Widget>ã§ããããšãç¥ã£ãŠããŠããemplace_backã«æž¡ãããåãæšæž¬ããå¿ èŠã¯ãããŸããã ãã®çµæãstd :: vector :: emplace_backãã©ã¡ãŒã¿ãŒã¯ãèŠããšããå³èŸºå€ãªã³ã¯ã§ããstd :: vector :: push_backããŒãžã§ã³ãã©ã¡ãŒã¿ãŒãšã¯ç°ãªãããŠãããŒãµã«ãªã³ã¯ã§ãã
åŒã巊蟺å€ã§ãããå³èŸºå€ã§ãããã¯ããã®åã«äŸåããªãããšã«æ³šæããŠãã ããã ã¿ã€ãintãæ€èšããŠãã ããã åintã®å·ŠèŸºå€ïŒããšãã°ãintã«ãã£ãŠå®£èšãããå€æ°ïŒãšãåintã®å³èŸºå€ïŒããšãã°ããªãã©ã«ãããšãã°10ïŒããããŸãã ããã¯ããŠã£ãžã§ããã®ãããªã«ã¹ã¿ã ã¿ã€ãã«åœãŠã¯ãŸããŸãã Widgetãªããžã§ã¯ãã¯ã巊蟺å€ïŒããšãã°ãWidgetå€æ°ïŒãŸãã¯å³èŸºå€ïŒããšãã°ããã¡ã¯ããªé¢æ°ãäœæãããWidgetãªããžã§ã¯ããè¿ããïŒã§ãã åŒã®ã¿ã€ãã¯ãããã巊蟺å€ãå³èŸºå€ããæããŸããã
Widget makeWidget(); // Widget Widget&& var1 = makeWidget(); // var1 lvalue, // var1 â rvalue ( Widget) Widget var2 = static_cast< Widget&& >(var1); // cast rvalue, // - rvalue ( Widget)
巊蟺å€ïŒããšãã°ãvar1ïŒãå³èŸºå€ã«å€æããäžè¬çãªæ¹æ³ã¯ãstd :: moveã䜿çšããããšã§ãããããã£ãŠãvar2ã¯æ¬¡ã®ããã«å®çŸ©ã§ããŸãã
Widget var2 = std::move(var1); //
ããšããšãåŒã®åãå³èŸºå€åç §ïŒWidget &&ïŒã§ããããšãæ瀺ããããã ãã«static_castã䜿çšããã³ãŒããåŒçšããŸããã
åå³èŸºå€åç §ã®ååä»ãå€æ°ãšãã©ã¡ãŒã¿ãŒã¯å·ŠèŸºå€ã§ãã ïŒã¢ãã¬ã¹ãååŸã§ããŸããïŒããäžåºŠããŠã£ãžã§ãããšã¬ãžã§ããã®ãã³ãã¬ãŒããæ€èšããŠãã ããã
template<typename T> class Widget { ... Widget(Widget&& rhs); // rhs - rvalue , ... // rhs lvalue }; template<typename T1> class Gadget { ... template <typename T2> Gadget(T2&& rhs);// rhs ... // rvalue }; // lvalue , rhs lvalue
Widgetã³ã³ã¹ãã©ã¯ã¿ãŒã§ã¯ãrhsã¯å³èŸºå€åç §ã§ãããããå³èŸºå€ã«é¢é£ä»ããããŠããïŒã€ãŸãå³èŸºå€ãæž¡ãããïŒããšãããããŸãããrhsèªäœã¯å·ŠèŸºå€ã§ããããããããå©çšããã«ã¯å³èŸºå€ã«å€æããå¿ èŠããããŸããã®rhsã¯å³èŸºå€ã«é¢é£ããŠããŸãã ååãšããŠã転éãœãŒã¹ãšããŠrhsã䜿çšããå¿ èŠããããããstd :: moveã䜿çšããŠå·ŠèŸºå€ãå³èŸºå€ã«å€æããŸãã åæ§ã«ãã¬ãžã§ããã³ã³ã¹ãã©ã¯ã¿ãŒã®rhsã¯æ±çšåç §ã§ããããã巊蟺å€ãŸãã¯å³èŸºå€ã«é¢é£ä»ããããšãã§ããŸããããããã«ããŠããrhsèªäœã¯å·ŠèŸºå€ã§ãã ãããå³èŸºå€ã«é¢é£ããŠããããããå©çšãããå Žåã¯ãrhsãå³èŸºå€ã«å€æããå¿ èŠããããŸãã ãã ãã巊蟺å€ã«é¢é£ä»ããããŠããå Žåãå³èŸºå€ãšããŠæ±ããããªãããšã¯ç¢ºãã§ãã ãŠãããŒãµã«ãªã³ã¯ãé¢é£ä»ããããŠãããã®ãžã®ãã®äŸåæ§ããstd :: forwardïŒã䜿çšããŠããŠãããŒãµã«ãªã³ã¯ãååŸããå³èŸºå€åŒã«é¢é£ä»ããããŠããå Žåã«ã®ã¿å³èŸºå€ã«å€æããçç±ã§ãã é¢æ°ã®ååïŒãforwardãïŒã¯ãåŒæ°åç §ã®ã¿ã€ãïŒå·ŠèŸºå€ãŸãã¯å³èŸºå€ïŒãåžžã«ç¶æãããŸãŸãå¥ã®é¢æ°ã«è»¢éãããšããæåŸ ãè£ä»ããŠããŸãã
ãã ããstd :: moveããã³std :: forwardã¯ããã®èšäºã®äž»é¡ã§ã¯ãããŸããã ãã®èšäºã§ã¯ãå宣èšã®&&ãå³èŸºå€ãªã³ã¯ãèšè¿°ããå Žåãšèšè¿°ããªãå Žåããããšããäºå®ã«ã€ããŠèª¬æããŠããŸãã æ°ãæ£ããªãããã«ãstd :: moveããã³std :: forwardã®è©³çŽ°ãªèª¬æã«ã€ããŠã¯ããè¿œå æ å ±ãã»ã¯ã·ã§ã³ã®ãªã³ã¯ãåç §ããŠãã ããã
现éš
ãã€ã³ãã¯ãC ++ 11ã®äžéšã®æ§æäœããªã³ã¯ãžã®ãªã³ã¯ãçæããC ++ã§ã¯ãªã³ã¯ãžã®ãªã³ã¯ãèš±å¯ãããªãããšã§ãã ãœãŒã¹ã³ãŒãã«ãªã³ã¯ãžã®ãªã³ã¯ãæ瀺çã«å«ãŸããŠããå Žåãã³ãŒãã¯æ£ãããããŸããã
Widget w1; ... Widget& & w2 = w1; // ! â â
ãã ããã³ã³ãã€ã«äžã«çºçããåã®æäœã®çµæãšããŠãªã³ã¯ãžã®ãªã³ã¯ãçºçããå Žåãããããã®ãããªå Žåããã®ã³ãŒããæåŠãããšåé¡ãçºçããŸãã ããã¯ãC ++ã®å ã®æšæºãã€ãŸãC ++ 98 / C ++ 03ã®çµéšããç¥ã£ãŠããŸãã
æ±çšåç §ã§ãããã³ãã¬ãŒããã©ã¡ãŒã¿ãŒã®åæšè«äžã«ãåãåã®å·ŠèŸºå€ãšå³èŸºå€ãããã€ãã®ç°ãªãåã«åºåãããŸãã ç¹ã«ãã¿ã€ãTã®å·ŠèŸºå€ã¯ã¿ã€ãTïŒïŒã€ãŸããTãžã®å·ŠèŸºå€åç §ïŒãšããŠåºåãããã¿ã€ãTã®å³èŸºå€ã¯åçŽã«åTãšããŠåºåãããŸãïŒå·ŠèŸºå€ã¯å·ŠèŸºå€åç §ãšããŠåºåãããå³èŸºå€åç §ãšããŠåºåãããªãããšã«æ³šæããŠãã ããïŒïŒå³èŸºå€ãšå·ŠèŸºå€ãæã€æ±çšåç §ãåãå ¥ãããã³ãã¬ãŒãé¢æ°ãåŒã³åºããšã©ããªãããèããŠã¿ãŸãããã
template<typename T> void f(T&& param); ... int x; ... f(10); // f rvalue f(x); // f lvalue
rvalue 10 Tã§fãåŒã³åºããšãintãšããŠåºåãããfã®ã€ã³ã¹ã¿ã³ã¹åã¯æ¬¡ã®ããã«ãªããŸãã
void f(int&& param); // f rvalue
ããã¯ããã§ãã ãã ãã巊蟺å€xãæã€fã®åŒã³åºãã§ã¯ãTã¯intïŒãšããŠåºåãããfã€ã³ã¹ã¿ã³ã¹ã«ã¯ãªã³ã¯ãžã®ãªã³ã¯ãå«ãŸããŸãã
void f(int& && param); // f lvalue
ãªã³ã¯ãžã®ãªã³ã¯ã®ããããã®ã€ã³ã¹ã¿ã³ã¹ã³ãŒãã¯äžèŠæ£ãããªãããã«èŠããŸããããœãŒã¹ã³ãŒããfïŒxïŒãã¯éåžžã«åççã§ãã ãã®ã³ãŒããæåŠããªãããã«ãC ++ã¯ããªã³ã¯ãžã®ãªã³ã¯ããã³ãã¬ãŒãã®ã€ã³ã¹ã¿ã³ã¹åãªã©ã®ã³ã³ããã¹ãã§è¡šç€ºããããšãã«ããªã³ã¯ã®æãããã¿ããå®è¡ããŸãã
2çš®é¡ã®ãªã³ã¯ïŒå·ŠèŸºå€ãªã³ã¯ãšå³èŸºå€ãªã³ã¯ïŒãããããã巊蟺ãªã³ã¯ãã巊蟺å€ãªã³ã¯ã巊蟺å€ãªã³ã¯ããå³èŸºå€ãªã³ã¯ãå³èŸºå€ãªã³ã¯ãã巊蟺å€ãªã³ã¯ãå³èŸºå€ãªã³ã¯ããå³èŸºå€ãªã³ã¯ã®4ã€ã®å¯èœãªçµã¿åããããããŸãã ãªã³ã¯ã®æãããã¿ã«ã¯2ã€ã®ã«ãŒã«ã®ã¿ããããŸãã
- å³èŸºå€ãªã³ã¯ãžã®å³èŸºå€ãªã³ã¯ã¯å³èŸºå€ãªã³ã¯ã«ãªããŸãïŒãæãããããïŒã
- ãªã³ã¯ãžã®ä»ã®ãã¹ãŠã®ãªã³ã¯ïŒã€ãŸãã巊蟺å€ãªã³ã¯ãå«ããã¹ãŠã®çµã¿åããïŒã¯ã巊蟺å€ãªã³ã¯ã«ãŸãšããããŸãã
ãããã®èŠåãé©çšããŠã巊蟺å€ã§fãã€ã³ã¹ã¿ã³ã¹åãããšã次ã®æ£ããã³ãŒããåŸãããŸãã
void f(int& param); // f lvalue
ããã«ãããïŒåã®æšè«ãšãªã³ã¯ã®æãããã¿ã®åŸã®ïŒãŠãããŒãµã«ãªã³ã¯ã巊蟺å€ãªã³ã¯ã«å€æã§ããæ£ç¢ºãªã¡ã«ããºã ãæäŸãããŸãã å®éããŠãããŒãµã«ãªã³ã¯ã¯ããªã³ã¯ãã©ãŒã«ãã£ã³ã°ã®ã³ã³ããã¹ãã«ãããåãªãå³èŸºå€ãªã³ã¯ã§ãã
ãªã³ã¯ã§ããå€æ°ã®åãæšå®ãããç¹å¥ãªç¶æ³ã ãã®å Žåããªã³ã¯ã瀺ãã¿ã€ãã®éšåã¯ç¡èŠãããŸãã ããšãã°ã
int x; ... int&& r1 = 10; // r1 - int&& int& r2 = x; // r2 - int&
ãã³ãã¬ãŒãfãåŒã³åºããšãã®r1ãšr2ã®äž¡æ¹ã®åã¯intãšèŠãªãããŸãã ãªã³ã¯ãåé€ãããã®åäœã¯ããžã§ããªãã¯åã®åæšè«èŠåã«äŸåããã巊蟺å€ã¯åTïŒãšããŠåºåãããå³èŸºå€ã¯åTãšããŠåºåãããããããããã®åŒã³åºãã§ã¯ã
f(r1); f(r2);
r1ãšr2ã®äž¡æ¹ã«å¯ŸããŠæšå®ãããåã¯intïŒã§ãã ãªãã§ïŒ æåã«ãã¿ã€ãr1ããã³r2ã®åç §éšåã¯ç Žæ£ããïŒäž¡æ¹ã®ã±ãŒã¹ã§intã«ãªããŸãïŒãããã巊蟺å€ã§ãããããäž¡æ¹ãfã®åŒã³åºãã®ãŠãããŒãµã«åç §ãã©ã¡ãŒã¿ãŒã®åæšè«äžã«intïŒãšããŠæ±ãããŸãã
åè¿°ã®ããã«ããªã³ã¯ã®æãããã¿ã¯ããã³ãã¬ãŒãã®ã€ã³ã¹ã¿ã³ã¹åãªã©ã®ã³ã³ããã¹ããã§çºçããŸãã 2çªç®ã®ãã®ãããªã³ã³ããã¹ãã¯ããèªåãå€æ°ã®å®çŸ©ã§ãã ã¿ã€ãTã®å·ŠèŸºå€ã¯ã¿ã€ãTïŒãæã¡ãã¿ã€ãTã®å³èŸºå€ã¯ã¿ã€ãTïŒãæã€ãšããŠåºåãããããããŠãããŒãµã«å€æ°ã§ããèªåå€æ°ã®ã¿ã€ãæšè«ã¯ããŠãããŒãµã«ãªãã¡ã¬ã³ã¹ã§ããé¢æ°ãã³ãã¬ãŒããã©ã¡ãŒã¿ãŒã®ã¿ã€ãæšè«ãšæ¬è³ªçã«åãã§ãã èšäºã®æåããããäžåºŠäŸãèããŠã¿ãŸãããã
Widget&& var1 = someWidget; // var1 Widget&& (auto ) auto&& var2 = var1; // var2 Widget& (. )
ã¿ã€ãvar1ã¯Widget &&ã§ãããvar2ãåæåããããšãã®ã¿ã€ãã®æšè«äžã«ãã®ãåç §éšåãã¯ç¡èŠãããŸãã ããã¯ãŠã£ãžã§ããã®äžçš®ãšèŠãªãããŸãã ããã¯ãŠãããŒãµã«åç §ïŒvar2ïŒã®åæåã«äœ¿çšããã巊蟺å€ã§ãããããæšå®ãããåã¯WidgetïŒã«ãªããŸãã var2å®çŸ©ã§autoã®ä»£ããã«WidgetïŒãä»£å ¥ãããšã次ã®ç¡å¹ãªã³ãŒããååŸãããŸãã
Widget& && var2 = var1; //
ãªã³ã¯ãæããããã åŸã«ãªããŸã
Widget& var2 = var1; // var2 Widget&
ãªã³ã¯ã®æãããã¿ã®3çªç®ã®ã³ã³ããã¹ãã¯ãtypedefã®åœ¢æãšäœ¿çšã§ãã ãã®ã¯ã©ã¹ãã³ãã¬ãŒããèãã
template<typename T> class Widget { typedef T& LvalueRefType; ... };
ãããŠããã®ãã³ãã¬ãŒãã®ãã®ãããªäœ¿çšã
Widget<int&> w;
ã€ã³ã¹ã¿ã³ã¹åãããã¯ã©ã¹ã«ã¯ã次ã®ïŒç¡å¹ãªïŒtypedefãå«ãŸããŸãã
typedef int& & LvalueRefType;
æãããã¿ãªã³ã¯ã¯ã次ã®æå¹ãªã³ãŒãã«ã€ãªãããŸãã
typedef int& LvalueRefType;
ããšãã°ããã®typedefãããããžã®åç §ã䜿çšããŠã³ã³ããã¹ãã§äœ¿çšãããšã
void f(Widget<int&>::LvalueRefType&& param);
typedefãå±éãããåŸã次ã®ç¡å¹ãªã³ãŒããçæãããŸãã
void f(int& && param);
ãã ãããªã³ã¯ãæãç³ããšåãæšãŠãããfã®æçµå®£èšã¯æ¬¡ã®ããã«ãªããŸãã
void f(int& param);
ãªã³ã¯ã®æãããã¿ãé©çšãããæåŸã®ã³ã³ããã¹ãã¯ãdecltypeã䜿çšããããšã§ãã ãã³ãã¬ãŒããšautoã®å Žåãšåæ§ã«ãdecltypeã¯TãŸãã¯TïŒã®ãããããäžããåŒã®åæšè«ãå®è¡ããdecltypeã¯C ++ 11ãªã³ã¯æãããã¿èŠåãé©çšããŸãã
, , decltype , auto . ( « » ), , decltype T (.. ), auto- T&. , decltype decltype ; ( ) . :
Widget w1, w2; auto&& v1 = w1; // v1 , // lvalue, v1 // lvalue w1. decltype(w1)&& v2 = w2; // v2 , decltype(w1) Widget, // v2 rvalue . // w2 lvalue, // rvalue lvalue, .
ãããã«
â&&â rvalue , â , lvalue rvalue . T&& T.
â ( rvalue , ) lvalue , rvalue . , . , auto-, typedef decltype.
è¬èŸ
Cassio Neri, Michal Mocny, Howard Hinnant, Andrei Alexandrescu, Stephan T. Lavavej, Roger Orr, Chris Oldwood, Jonathan Wakely Anthony Williams. , .
è¿œå æ å ±
C++11, Wikipedia.
Overview of the New C++ (C++11), Scott Meyers, Artima Press, last updated January 2012.
C++ Rvalue References Explained, Thomas Becker, last updated September 2011.
decltype, Wikipedia.
âA Note About decltype,â Andrew Koenig, Dr. Dobb's, 27 July 2011.