Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Effective Modern C++ 読書会 Item29, Item30
Search
Linda_pp
July 16, 2015
Technology
0
450
Effective Modern C++ 読書会 Item29, Item30
Item29: move に期待しすぎないようにしよう
Item30: perfect forwarding に失敗する場合を知ろう
Linda_pp
July 16, 2015
Tweet
Share
More Decks by Linda_pp
See All by Linda_pp
actionlint の Linter 設計
rhysd
6
4.9k
ripgrep をライブラリとして使う
rhysd
0
440
port-monolith-to-wasm-for-chrome-extension
rhysd
0
470
Fuzzing Rust Text Editor
rhysd
1
3k
Vim compiled to WebAssembly
rhysd
5
2.2k
about-neovim-0.4.0-floating-window
rhysd
3
2.2k
reply.vim
rhysd
0
1.2k
Vim ported to WebAssembly (VimConf 2018)
rhysd
4
3.3k
go-selfupdate-github で ツールを自己アップデートする
rhysd
5
4.3k
Other Decks in Technology
See All in Technology
ESXi で仮想化した ARM 環境で LLM を動作させてみるぞ
unnowataru
0
180
AIエージェント時代のエンジニアになろう #jawsug #jawsdays2025 / 20250301 Agentic AI Engineering
yoshidashingo
8
3.7k
EMConf JP 2025 懇親会LT / EMConf JP 2025 social gathering
sugamasao
2
190
EDRの検知の仕組みと検知回避について
chayakonanaika
12
4.9k
内製化を加速させるlaC活用術
nrinetcom
PRO
2
140
JAWS FESTA 2024「バスロケ」GPS×サーバーレスの開発と運用の舞台裏/jawsfesta2024-bus-gps-serverless
ma2shita
3
160
DevinでAI AWSエンジニア製造計画 序章 〜CDKを添えて〜/devin-load-to-aws-engineer
tomoki10
0
120
Aurora PostgreSQLがCloudWatch Logsに 出力するログの課金を削減してみる #jawsdays2025
non97
1
200
AWSアカウントのセキュリティ自動化、どこまで進める? 最適な設計と実践ポイント
yuobayashi
7
610
JavaにおけるNull非許容性
skrb
2
2.6k
What's new in Go 1.24?
ciarana
1
110
ウォンテッドリーのデータパイプラインを支える ETL のための analytics, rds-exporter / analytics, rds-exporter for ETL to support Wantedly's data pipeline
unblee
0
130
Featured
See All Featured
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
30
4.6k
Why Our Code Smells
bkeepers
PRO
336
57k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
33
2.1k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
251
21k
Navigating Team Friction
lara
183
15k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
40
2k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
GitHub's CSS Performance
jonrohan
1030
460k
YesSQL, Process and Tooling at Scale
rocio
172
14k
A Modern Web Designer's Workflow
chriscoyier
693
190k
Building Applications with DynamoDB
mza
93
6.2k
Mobile First: as difficult as doing things right
swwweet
223
9.4k
Transcript
Effective Modern C++ ಡॻձ Item29, Item 30 @Linda_pp @rhysd
Item 29: moveʹظ͗͢͠Δͳ ʢAssume that move operations are not present,
not cheap, and not used)
move • move C++11 ͷۄػೳͷͻͱͭ • C++03 ͷίʔυ C++11
ͰϏϧυ͠ͳ͓ͤ ͘ͳΔʂ • STL move ରԠ • ίϯςφͷίϐʔ͕ϙΠϯλ1ͭͷίϐʔʹͳΔ ͧʂ
࣮ࡍ move ͕ࢥͬͨ΄Ͳ༗ ༻Ͱͳ͍߹͕ͨ͘͞Μ͋Δ
move ૢ࡞͕ଘࡏ͠ͳ͍࣌ ҉ͷ move Λఆٛ͞ΕΔ͕݅ݫ͍͠ • copyૢ࡞ɼmoveૢ࡞ɼσετϥΫλ͕ Ϣʔβఆٛ͞Ε͍ͯͳ͍ (Item17)
• جఈΫϥε͕moveඇରԠͰͳ͍ (Item11)
move ૢ࡞ͷίετ͕͘ͳ ͍࣌ ΄ͱΜͲͷ STL ίϯςφͷ move → ώʔϓ ͷϙΠϯλ
ͷషΓସ͚͑ͩͰྑ͍ʢ O(1) ʣ DPOUBJOFS CV⒎FS DPOUBJOFS NPWF
move ૢ࡞ͷίετ͕͘ͳ ͍࣌ std::array → ֤ཁૉͷ move ͔͠Ͱ͖ͳ͍ʢ O(n) ʣ
TUEBSSBZ CV⒎FS NPWF TUEBSSBZ CV⒎FS
move ૢ࡞ͷίετ͕͘ͳ ͍࣌ std::string →Small String Optimization • খ͍͞จࣈྻ
stack ʹऔΔ • 64bit OS, libc++ ͳΒ 24 จࣈ·Ͱ • move std::array ͷΑ͏ʹ 0(n) ͔͔Δ
move ૢ࡞͕͑ͳ͍࣌ ྫ֎҆શͳૢ࡞Λఏڙ͢Δίϯςφʢྫɿ std::vector ͷιʔτʣ → ཁૉͷ move ͕ྫ֎Λ ͛Δͱ͖
copy ʹ fallback • ཁૉͷ move தʹྫ֎͕ൃੜ͢Δͱ vector ͷ move ͕ྃͰ͖ͳ͍
move ͕༗ޮͰͳ͍࣌·ͱΊ • move ૢ࡞͕ଘࡏ͠ͳ͍ͱ͖ → ҉ͷ move ݅ݫ͍͠ •
move ૢ࡞͕͘ͳ͍ͱ͖ → std::array • move ૢ࡞͕͑ͳ͍ͱ͖ → std::vector ͷཁૉ͕ྫ֎҆શ ʹ move Ͱ͖ͳ͍࣌ • lvalue ͷͱ͖ → Ұ෦ͷྫ֎ʢ҉ͷ moveʣΛআ͍ͯ lvalue move Ͱ͖ͳ͍
Things to Remember • ςϯϓϨʔτΛ͍ͬͯΔ࣌ͲΜͳܕ͕ͬ ͯ͘Δ͔Θ͔Βͳ͍ → move ʹ͍ͭͯอक తʹίʔυΛॻ͘
• ѻ͏ܕͷৄࡉ͕͔͍ͬͯΔ → ܕͷυΩϡϝ ϯτΛಡΜͰ move ͕༗༻Ͱ͋ΕͦΕʹґ ଘͨ͠ίʔυΛॻ͍ͯྑ͍
Item 30: perfect forwarding ʹࣦഊ͢Δ߹ΛΖ͏
Perfect Forwarding Universal Reference Λ͍ɼؔͷҾΛ (const-ness ؚΊͯʣผͷؔݺͼग़͠ʹ ͦͷ··సૹ͢Δ 1
// perfect forward する関数 fwd 2 template<class... Ts> 3 auto fwd(Ts&& ... args) 4 { 5 // 関数 f に引数をそのまま転送する 6 return f(std::foward<Ts>(args)...); 7 } 8 9 ... 10 11 // 引数によっては perfect forwarding が失敗する 12 fwd({expression});
Perfect Forwarding ͕͏·͘ ͍͔ͳ͍Τοδέʔε ɾ{} ʹΑΔॳظԽ ɾ0 NULL ΛψϧϙΠϯλͱͯ͠͏
ɾએݴ͚ͩͷ static const ·ͨ constexpr σʔλϝϯό ɾΦʔόʔϩʔυ͞Εͨؔ ɾؔςϯϓϨʔτ ɾϏοτϑΟʔϧυ
{} ʹΑΔॳظԽ 1 void f(const std::vector<int>&); 2 3 ... 4
5 // OK. std::vector<int> は {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.
{} ʹΑΔॳظԽ • f Λݺͼग़ͨ͠߹ɼίϯύΠϥ f ͷҾ ͔Β {1,2,3} Λ
vector ʹ҉ม͢Εྑ ͍͜ͱ͕͔Δ • fwd Λͬͯؒతʹݺͼग़ͨ͠߹ɼfwd ͷҾ Universal Reference ͷͨΊɼ{1,2,3} ΛͲͷܕʹม͢Εྑ͍ͷ͔͔Βͳ͍
ͳͥ std::initializer_list<int> ʹ ͳΒͳ͍ͷ͔ • Ҿ͕ std::initializer_list ͱ໌ࣔ͞Ε͍ͯͳ͍ ݶΓɼinitializer_list ʹਪ͞Εͳ͍ʢnon-
deduced contextʣ • ҎԼͷ߹ auto ͷਪ OK 1 // auto が std::initializer_list<int> に推論される 2 auto il = {1, 2, 3}; 3 4 // OK.すでに推論済み 5 fwd(il);
0 NULL ΛψϧϙΠϯλʹ ͬͨ߹ 0 NULL ܕʹਪ͞Εͯ͠·͏ͨΊ ϙΠϯλʹมͰ͖ͳ͍ʢItem8ʣˠ
nullptr Λ͑OK 1 void f(int *) 2 {} 3 4 template<class... Args> 5 void fwd(Args &&... args) 6 { 7 return f(std::forward<Args>(args)...); 8 } 9 10 fwd(NULL);
એݴ͚ͩͷ 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); // リンクエラー
એݴ͚ͩͷ static const ·ͨ constexpr σʔλϝϯό • f ͷ߹ MinVals
ͷ͕͠͞ΕΔͷͰ OK • fwd ͷ߹ɼUniversal Reference ࢀরͳͷ ͰɼMinVals ͷΞυϨε͕ඞཁʹͳΔ → Ϧϯ ΫΤϥʔ • ԼهͷΑ͏ʹ࣮ମΛఆ͓͚ٛͯ͠ OK const size_t Widget::MinVals;
Φʔόʔϩʔυ͞Εͨؔ 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); // コンパイルエラー!
Φʔόʔϩʔυ͞Εͨؔ • f ͷݺͼग़͠ͰҾͷܕ͔Β processVal ͷ ΦʔόʔϩʔυΛղܾͰ͖Δ • fwd ͷݺͼग़͠ͰҾ
Universal Reference ͷͨΊɼprocessVal ͷΦʔόʔ ϩʔυ͕ղܾͰ͖ͳ͍ • ԼهͷΑ͏ͳ߹ OK int (*p)(int) = processVal; // ͜͜ͰΦʔόʔϩʔυղܾࡁΈ fwd(p); // OK
ؔςϯϓϨʔτ Φʔόʔϩʔυͷ߹ͱಉ͡ 1 template<class T> 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
ϏοτϑΟʔϧυ 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); // コンパイルエラー!
ϏοτϑΟʔϧυ • ϏοτϑΟʔϧυͷΞΫηεඇconstࢀর → fwd ͷҾඇconstࢀরʹͳΔ → Ϗοτ ϑΟʔϧυඇconstࢀরʹଋറͰ͖ͳ͍ •
ಛఆͷϏοτϑΟʔϧυΛࢦ͢ϙΠϯλ͕ͭ ͘Εͳ͍ͷͱಉ͡ • ίϐʔΛͭ͘Ε OK 1 IPv4Header h; 2 3 auto length = static_cast<std::uint16_t>(totalLength); 4 5 fwd(length); // OK
·ͱΊ • Perfect Forwarding େͷ߹ࢥͬͨ௨ Γಈ͘ • ྫʹग़ͨΑ͏ͳكʹ͏·͍͔͘ͳ͍έʔε͕ ͋Δ •
ϫʔΫΞϥϯυΛ͓ͬͯ͘ͷ͕େࣄ
Things to Remember • Perfect Forwarding ࣦഊ͢Δ߹ • సૹؔͷҾͷܕͷਪʹࣦഊͨ࣌͠ •
సૹؔͷҾͷܕΛؒҧͬͨʢf ʹͤͳ͍ʣܕʹਪͯ͠͠·ͬͨ࣌ • ͦͷଞͷΤοδέʔε • {} ʹΑΔॳظԽ • 0 NULL ΛψϧϙΠϯλͱͯ͠͏ • એݴ͚ͩͷ static const ·ͨ constexpr σʔλϝϯό • Φʔόʔϩʔυ͞Εͨؔ • ؔςϯϓϨʔτ • ϏοτϑΟʔϧυ