Slide 1

Slide 1 text

Effective Modern C++ ಡॻձ Item29, Item 30 @Linda_pp @rhysd

Slide 2

Slide 2 text

Item 29: moveʹظ଴͗͢͠Δͳ ʢAssume that move operations are not present, not cheap, and not used)

Slide 3

Slide 3 text

move • move ͸ C++11 ͷ໨ۄػೳͷͻͱͭ • C++03 ͷίʔυ΋ C++11 ͰϏϧυ͠ͳ͓ͤ͹ ଎͘ͳΔʂ • STL ͸ move ରԠ • ίϯςφͷίϐʔ͕ϙΠϯλ1ͭͷίϐʔʹͳΔ ͧʂ

Slide 4

Slide 4 text

࣮ࡍ͸ move ͕ࢥͬͨ΄Ͳ༗ ༻Ͱͳ͍৔߹͕ͨ͘͞Μ͋Δ

Slide 5

Slide 5 text

move ૢ࡞͕ଘࡏ͠ͳ͍࣌ ҉໧ͷ move Λఆٛ͞ΕΔ৚͕݅ݫ͍͠ • copyૢ࡞ɼmoveૢ࡞ɼσετϥΫλ͕ Ϣʔβఆٛ͞Ε͍ͯͳ͍ (Item17) • جఈΫϥε͕moveඇରԠͰͳ͍ (Item11)

Slide 6

Slide 6 text

move ૢ࡞ͷίετ͕௿͘ͳ ͍࣌ ΄ͱΜͲͷ STL ίϯςφͷ move → ώʔϓ΁ ͷϙΠϯλ ͷషΓସ͚͑ͩͰྑ͍ʢ O(1) ʣ DPOUBJOFS CV⒎FS DPOUBJOFS NPWF

Slide 7

Slide 7 text

move ૢ࡞ͷίετ͕௿͘ͳ ͍࣌ std::array → ֤ཁૉͷ move ͔͠Ͱ͖ͳ͍ʢ O(n) ʣ TUEBSSBZ CV⒎FS NPWF TUEBSSBZ CV⒎FS

Slide 8

Slide 8 text

move ૢ࡞ͷίετ͕௿͘ͳ ͍࣌ std::string →Small String Optimization • খ͍͞จࣈྻ͸ stack ʹऔΔ • 64bit OS, libc++ ͳΒ 24 จࣈ·Ͱ • move ͸ std::array ͷΑ͏ʹ 0(n) ͔͔Δ

Slide 9

Slide 9 text

move ૢ࡞͕࢖͑ͳ͍࣌ ྫ֎҆શͳૢ࡞Λఏڙ͢Δίϯςφʢྫɿ std::vector ͷιʔτʣ → ཁૉͷ move ͕ྫ֎Λ౤ ͛Δͱ͖ copy ʹ fallback • ཁૉͷ move தʹྫ֎͕ൃੜ͢Δͱ vector ͷ move ͕׬ྃͰ͖ͳ͍

Slide 10

Slide 10 text

move ͕༗ޮͰͳ͍࣌·ͱΊ • move ૢ࡞͕ଘࡏ͠ͳ͍ͱ͖ → ҉໧ͷ move ৚݅͸ݫ͍͠ • move ૢ࡞͕଎͘ͳ͍ͱ͖ → std::array • move ૢ࡞͕࢖͑ͳ͍ͱ͖ → std::vector ͷཁૉ͕ྫ֎҆શ ʹ move Ͱ͖ͳ͍࣌ • lvalue ͷͱ͖ → Ұ෦ͷྫ֎ʢ҉໧ͷ moveʣΛআ͍ͯ lvalue ͸ move Ͱ͖ͳ͍

Slide 11

Slide 11 text

Things to Remember • ςϯϓϨʔτΛ࢖͍ͬͯΔ࣌͸ͲΜͳܕ͕౉ͬ ͯ͘Δ͔Θ͔Βͳ͍ → move ʹ͍ͭͯ͸อक తʹίʔυΛॻ͘ • ѻ͏ܕͷৄࡉ͕෼͔͍ͬͯΔ → ܕͷυΩϡϝ ϯτΛಡΜͰ move ͕༗༻Ͱ͋Ε͹ͦΕʹґ ଘͨ͠ίʔυΛॻ͍ͯྑ͍

Slide 12

Slide 12 text

Item 30: perfect forwarding ʹࣦഊ͢Δ৔߹Λ஌Ζ͏

Slide 13

Slide 13 text

Perfect Forwarding Universal Reference Λ࢖͍ɼؔ਺ͷҾ਺Λ (const-ness ౳΋ؚΊͯʣผͷؔ਺ݺͼग़͠ʹ ͦͷ··సૹ͢Δ 1 // perfect forward する関数 fwd 2 template 3 auto fwd(Ts&& ... args) 4 { 5 // 関数 f に引数をそのまま転送する 6 return f(std::foward(args)...); 7 } 8 9 ... 10 11 // 引数によっては perfect forwarding が失敗する 12 fwd({expression});

Slide 14

Slide 14 text

Perfect Forwarding ͕͏·͘ ͍͔ͳ͍Τοδέʔε ɾ{} ʹΑΔॳظԽ ɾ0 ΍ NULL ΛψϧϙΠϯλͱͯ͠࢖͏ ɾએݴ͚ͩͷ static const ·ͨ͸ constexpr σʔλϝϯό ɾΦʔόʔϩʔυ͞Εͨؔ਺ ɾؔ਺ςϯϓϨʔτ ɾϏοτϑΟʔϧυ

Slide 15

Slide 15 text

{} ʹΑΔॳظԽ 1 void f(const std::vector&); 2 3 ... 4 5 // OK. std::vector は {1, 2, 3} で初期化される 6 f( {1, 2, 3} ); 7 8 // コンパイルエラー! 9 fwd( {1, 2, 3} ); foo.cpp:15:5: error: no matching function for call to 'fwd' fwd({1, 2, 3}); ^~~ ! foo.cpp:8:6: note: candidate function not viable: requires 0 arguments, but 1 was provided void fwd(Args &&... args) ^ 1 error generated.

Slide 16

Slide 16 text

{} ʹΑΔॳظԽ • f Λ௚઀ݺͼग़ͨ͠৔߹ɼίϯύΠϥ͸ f ͷҾ ਺͔Β {1,2,3} Λ vector ʹ҉໧ม׵͢Ε͹ྑ ͍͜ͱ͕෼͔Δ • fwd Λ࢖ͬͯؒ઀తʹݺͼग़ͨ͠৔߹ɼfwd ͷҾ਺͸ Universal Reference ͷͨΊɼ{1,2,3} ΛͲͷܕʹม׵͢Ε͹ྑ͍ͷ͔෼͔Βͳ͍

Slide 17

Slide 17 text

ͳͥ std::initializer_list ʹ ͳΒͳ͍ͷ͔ • Ҿ਺͕ std::initializer_list ͱ໌ࣔ͞Ε͍ͯͳ͍ ݶΓɼinitializer_list ʹ͸ਪ࿦͞Εͳ͍ʢnon- deduced contextʣ • ҎԼͷ৔߹ auto ͷਪ࿦͸ OK 1 // auto が std::initializer_list に推論される 2 auto il = {1, 2, 3}; 3 4 // OK.すでに推論済み 5 fwd(il);

Slide 18

Slide 18 text

0 ΍ NULL ΛψϧϙΠϯλʹ ࢖ͬͨ৔߹ 0 ΍ NULL ͸੔਺ܕʹਪ࿦͞Εͯ͠·͏ͨΊ ϙΠϯλʹม׵Ͱ͖ͳ͍ʢItem8ʣˠ nullptr Λ࢖͑͹OK 1 void f(int *) 2 {} 3 4 template 5 void fwd(Args &&... args) 6 { 7 return f(std::forward(args)...); 8 } 9 10 fwd(NULL);

Slide 19

Slide 19 text

એݴ͚ͩͷ static const ·ͨ͸ constexpr σʔλϝϯό Undefined symbols for architecture x86_64: "Widget::MinVals", referenced from: _main in foo-4cf4cf.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) ! ※ clang 3.4 ͙Β͍·Ͱ͸ίϯύΠϧ௨ͬͯ͠·͏ 1 struct Widget { 2 static constexpr int MinVals = 28; // 定義ではなく宣言 3 }; 4 5 void f(size_t val); 6 7 ... 8 9 f(Widget::MinVals); // OK 10 11 fwd(Widget::MinVals); // リンクエラー

Slide 20

Slide 20 text

એݴ͚ͩͷ static const ·ͨ͸ constexpr σʔλϝϯό • f ͷ৔߹͸ MinVals ͷ஋͕஋౉͠͞ΕΔͷͰ OK • fwd ͷ৔߹ɼUniversal Reference ͸ࢀরͳͷ ͰɼMinVals ͷΞυϨε͕ඞཁʹͳΔ → Ϧϯ ΫΤϥʔ • ԼهͷΑ͏ʹ࣮ମΛఆ͓͚ٛͯ͠͹ OK const size_t Widget::MinVals;

Slide 21

Slide 21 text

Φʔόʔϩʔυ͞Εͨؔ਺ foo.cpp:24:5: error: no matching function for call to 'fwd' fwd(processVal); ^~~ foo.cpp:17:6: note: candidate function not viable: requires 0 arguments, but 1 was provided void fwd(Args &&... args) ^ 1 error generated. 1 int processVal(int val); 2 int processVal(int val, int priority); 3 4 void f(int (*fp)(int)); 5 6 ... 7 8 f(processVal); // OK 9 10 fwd(processVal); // コンパイルエラー!

Slide 22

Slide 22 text

Φʔόʔϩʔυ͞Εͨؔ਺ • f ͷݺͼग़͠Ͱ͸Ҿ਺ͷܕ͔Β processVal ͷ ΦʔόʔϩʔυΛղܾͰ͖Δ • fwd ͷݺͼग़͠Ͱ͸Ҿ਺͸ Universal Reference ͷͨΊɼprocessVal ͷΦʔόʔ ϩʔυ͕ղܾͰ͖ͳ͍ • ԼهͷΑ͏ͳ৔߹͸ OK int (*p)(int) = processVal; // ͜͜ͰΦʔόʔϩʔυղܾࡁΈ fwd(p); // OK

Slide 23

Slide 23 text

ؔ਺ςϯϓϨʔτ Φʔόʔϩʔυͷ৔߹ͱ࿩͸ಉ͡ 1 template 2 int processVal(T val); 3 4 void f(int (*fp)(int)); 5 6 ... 7 8 f(processVal); // OK 9 10 fwd(processVal); // T が解決できないため NG

Slide 24

Slide 24 text

ϏοτϑΟʔϧυ foo.cpp:25:9: error: non-const reference cannot bind to bit-field 'totalLength' fwd(h.totalLength); ^~~~~~~~~~~~~ foo.cpp:9:17: note: bit-field is declared here totalLength:16; ^ 1 error generated. 1 struct IPv4Header { 2 std::uint32_t version:4, 3 IHL:4, 4 DSCP:6, 5 ECN:2, 6 totalLength:16; 7 }; 8 9 void f(size_t s); 10 11 ... 12 13 IPv4Header h; 14 15 f(h.totalLength); // OK 16 fwd(h.totalLength); // コンパイルエラー!

Slide 25

Slide 25 text

ϏοτϑΟʔϧυ • ϏοτϑΟʔϧυ΁ͷΞΫηε͸ඇconstࢀর → fwd ͷҾ਺͸ඇconstࢀরʹͳΔ → Ϗοτ ϑΟʔϧυ͸ඇconstࢀরʹଋറͰ͖ͳ͍ • ಛఆͷϏοτϑΟʔϧυΛࢦ͢ϙΠϯλ͕ͭ ͘Εͳ͍ͷͱಉ͡ • ίϐʔΛͭ͘Ε͹ OK 1 IPv4Header h; 2 3 auto length = static_cast(totalLength); 4 5 fwd(length); // OK

Slide 26

Slide 26 text

·ͱΊ • Perfect Forwarding ͸େ఍ͷ৔߹͸ࢥͬͨ௨ Γಈ͘ • ྫʹग़ͨΑ͏ͳكʹ͏·͍͔͘ͳ͍έʔε͕ ͋Δ • ϫʔΫΞϥ΢ϯυΛ஌͓ͬͯ͘ͷ͕େࣄ

Slide 27

Slide 27 text

Things to Remember • Perfect Forwarding ࣦഊ͢Δ৔߹ • సૹؔ਺ͷҾ਺ͷܕͷਪ࿦ʹࣦഊͨ࣌͠ • సૹؔ਺ͷҾ਺ͷܕΛؒҧͬͨʢf ʹ౉ͤͳ͍ʣܕʹਪ࿦ͯ͠͠·ͬͨ࣌ • ͦͷଞͷΤοδέʔε • {} ʹΑΔॳظԽ • 0 ΍ NULL ΛψϧϙΠϯλͱͯ͠࢖͏ • એݴ͚ͩͷ static const ·ͨ͸ constexpr σʔλϝϯό • Φʔόʔϩʔυ͞Εͨؔ਺ • ؔ਺ςϯϓϨʔτ • ϏοτϑΟʔϧυ