Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
return文におけるstd::moveについて
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
onihusube
December 20, 2024
Programming
2.9k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
return文におけるstd::moveについて
return文でstd::moveをいつ使うべきかとその理由を完全理解してください💪
onihusube
December 20, 2024
More Decks by onihusube
See All by onihusube
非侵入的モナド的操作導入ライブラリ harmony とコンセプト・CPO
onihusube
0
240
Other Decks in Programming
See All in Programming
thread_parallel_with_free-threaded_Python_and_NumPy.pdf
riku_sakamoto
0
350
更なる可用性を求めて、5年間運用したKotlinのアプリケーションをGoでリプレイスする話
ken_tunc
0
290
SREの越境 / SRE Collaboration
y0hgi
2
240
Heart of Swift Concurrency
koher
0
910
世界の中心で、AI(App Intents)をさけぶ ー App Intents中心設計の実践ガイド
touyou
0
610
Intent as Code
shoppingjaws
6
1k
AGENTS.md Is Not Enough:Build Skills, Don't Download Them
lx_t
0
120
Jetpack Compose メカニズム
skydoves
0
440
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
180
GKE で Pod の見方を変えたら、スケールアウト時の挙動を真に捉えられた話
stkk
0
130
Vibes Containers 〜AIで変わるコンテナ設計と運用〜
tkikuc
3
550
GraphRAGのKnowledge Graphを 直接!見る/View-GraphRAG's-KnowledgeGraph-directly!
tyumugi1113
1
340
Featured
See All Featured
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
200
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.4k
A Tale of Four Properties
chriscoyier
163
24k
Navigating Team Friction
lara
192
16k
How to make the Groovebox
asonas
2
2.4k
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
0
240
Fashionably flexible responsive web design (full day workshop)
malarkey
409
67k
Thoughts on Productivity
jonyablonski
76
5.4k
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
430
The agentic SEO stack - context over prompts
schlessera
0
940
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
850
svc-hook: hooking system calls on ARM64 by binary rewriting
retrage
2
580
Transcript
return文における std::move()について いつstd::moveするべきか?
自己紹介 • C++の沼に嵌って抜け出せない人です • C++が好きです • この名前だと、CEDECでC++の発表を2回くらいしています • インターネットだとキノコのアイコンで活動しています •
物理世界では、株式会社T2という自動運転の会社でC++書いて ます • C++プログラマ積極募集中です! 2
背景 • 以前に書いた本の売り文句に「return文でいつstd::move()をす るべきか完全理解できる!」のようなことを書いた • しかし、本文には明確にその回答を書いていなかった • ずっと気になっていたが、いい機会なのでここで回答を置いて おくことに 以前書いた本
3
目的 • return文でいつstd::move()を書くべきかその理由を完全理解す る • C++17以降を対象とします 4
return文とstd::move • とても典型的には次のようなコードにおいて、return文での std::move()の使用をコンパイラに怒られる auto f() -> std::vector<int> { std::vector
vec = {1, 2, 3, 4}; ... return std::move(vec); // 警告 } g++13.2: warning: moving a local object in a return statement prevents copy elision [-Wpessimizing-move] clang 17.0.1: warning: moving a local object in a return statement prevents copy elision [- Wpessimizing-move] 5
return文とstd::move • std::move()を外すととりあえず何も言われなくなる • でも… • 本当にムーブされてるのか不安 • というかむしろ、std::move()を付けろと怒られた記憶もある •
人もいると思う auto f() -> std::vector<int> { std::vector vec = {1, 2, 3, 4}; ... return vec; // } 6
結果 • return文でいつstd::move()すればいいのかよくわからない • した方が良いように思えるけれど、しなくてもいいの? • とりあえずstd::move()してみてコンパイラに怒られたら外す、 という運用 • コードベースによっては非効率
7
何が分からないのか? • なぜ怒られているのか分からない • RVOと暗黙ムーブ周りの仕様は複雑すぎる • ムーブされているかはコードから見えないので起きていること が分からない • 本当にムーブされているのか?
• むしろ逆の指摘を受けたことがある場合、いつstd::move()が必 要なのか何も分からない ➢「なぜダメなのか?」と「いつ要るのか?」を理解する! 8
なぜ怒られている? • 警告メッセージにある通り、コピー省略最適化を阻害するから • ここでのコピー省略最適化とは、いわゆるNRVOのこと 9 g++13.2: warning: moving a
local object in a return statement prevents copy elision [-Wpessimizing-move] clang 17.0.1: warning: moving a local object in a return statement prevents copy elision [- Wpessimizing-move]
Named Return Value Optimization(NRVO) • 戻り値を引数の参照から返すようにするような最適化 // この関数にNRVOが適用されると auto f()
-> std::vector<int> { std::vector vec = {1, 2, 3, 4}; ... return vec; } // あたかもこう書き替えられたかのように動作する void f(std::vector& ret) { ret = std::vector{1, 2, 3, 4}; ... } 10
なぜNRVOが阻害されるのか? • NRVOは必須ではなく、あくまで許可されている最適化 • そのため、規格ではその適用範囲が指定されている • NRVOの対象となるreturn文は、そのオペランドが丁度変数名 でなければならない • かつ、その変数名はその関数ローカルの非volatile変数であり、関数引
数でもcatch節のパラメータでもない、必要がある • 戻り値型は非参照型 ➢return文のオペランドで関数呼び出ししていると、NRVOできない 11
なぜ関数呼び出しはダメなのか? • ex_func()が中で何をしてるか分からない • ex_func()に渡しているものと帰っているものが一致する保証がない • 定義が見えていればできる場合もあるかもしれないが、現在の 規格ではそこまでの解析を要求していない // こんな素性の良く分からない関数があったとして
auto ex_func(std::vector<int>&) -> std::vector<int>&&; auto f() -> std::vector<int> { std::vector vec = {1, 2, 3, 4}; // NRVO出来そうに見えますか・・・? return ex_func(vec); } 12
std::move()はライブラリ関数! • 先程のex_func()とstd::move()はNRVOの観点で見ると、コンパ イラの視点では差が無い • 規格でもstd::move()やstd::forward()をNRVOにおいて特別扱い すべしとは書いていない • おそらく実装負荷を考慮してのこと •
除外する提案は最近された(P2991R0) • 結果、return文におけるあらゆる関数呼び出しはNRVOを阻害 してしまう • 確実に行われなくする 13
ほとんどの場合std::move()は必要ない • std::move()をしなくても、暗黙ムーブされるため • 暗黙ムーブの対象は • C++17まで: ローカルの非volatile変数 • C++20以降:
+ローカルの非volatile右辺値参照 • return文のオペランドは変数名 • あるいは、()で囲まれていても良い ➢return文における関数呼び出しは暗黙ムーブも阻害する • 上記を満たしたうえで • C++20までは、return文でコピーが起こる場合、代わりにまずムーブ を試みる • C++23からは、オペランドがxvalueとして扱われる 14
暗黙ムーブのバージョンごとの対象範囲 • C++11 • 戻り値型と同じ非参照ローカル変数の暗黙ムーブ • オペランド型の右辺値を受ける変換コンストラクタへの暗黙ムーブ • C++20 •
ローカル右辺値参照の暗黙ムーブ • 変換演算子による戻り値型への変換時の暗黙ムーブ • 戻り値型コンストラクタへの暗黙ムーブ • 派生クラスから基底クラスへの変換が起こる場合の暗黙ムーブ • C++23 • 戻り値型が参照型の場合の暗黙ムーブ 15
暗黙ムーブの一例 auto ex_11(std::vector<int> vec) -> std::vector<int> { return vec; //
暗黙ムーブ、C++11から } auto ex_20(std::vector<int>&& vec) -> std::vector<int> { return vec; // 暗黙ムーブ、C++20から } auto ex_23(std::vector<int>&& vec) -> std::vector<int>&& { return vec; // 暗黙ムーブ、C++23から } 16
それでもstd::move()が必要な場合 • C++20の場合、C++23で許可された範囲のもの • 戻り値型が右辺値参照型であり、ローカルの右辺値参照をreturnする 場合 • C++23以降はこれも暗黙ムーブ対象なのでstd::move()は不要 • とはいえこの場合はあっても警告はされないはず
• std::move()そのもののような場合を除いて普通はこんなコード書かないでしょ auto f(std::vector<int>&& vec) -> std::vector<int>&& { // 戻り値型が右辺値参照型の場合のローカル右辺値参照の暗黙ムーブ return vec; // C++20まで // C++20まではstd::move()必須 return std::move(vec); // } 17
それでもstd::move()が必要な場合 • C++17までなら、C++20以降で許可された範囲のもの • 次の場合、C++17では暗黙ムーブ対象ではない • ローカル右辺値参照の暗黙ムーブ • 変換演算子による戻り値型への変換時の暗黙ムーブ •
戻り値型コンストラクタへの暗黙ムーブ • 派生クラスから基底クラスへの変換が起こる場合の暗黙ムーブ • returnしようとする値と戻り値型が異なる場合、とほぼまとめられる 18
C++17で暗黙ムーブされない例 auto f1(std::vector<int>&& vec) -> std::vector<int> { return vec; //
右辺値参照の暗黙ムーブ、C++20から } struct To { operator std::vector<int>() &&; }; auto f2(To t) -> std::vector<int> { return t; // 暗黙ムーブによる変換演算子適用、C++20から } struct V { V(std::vector<int>); }; auto f3(std::vector<int> vec) -> V { return vec; // コンストラクタ引数への暗黙ムーブ、C++20から } auto f4(Derived d) -> Base { return d; // 基底クラスへの変換時の暗黙ムーブ、C++20から } 19
それでもstd::move()が必要な場合 • 言語バージョンとは関係なく必要な場合がある • 戻り値型のコンストラクタを明示的に呼び出す場合 • 特に、2引数以上を渡そうとする場合 • return文のオペランドが変数名ではなくなるため •
同様に、return文で関数呼び出ししているとその引数は暗黙ムーブ されない • が、これはあまり驚きはなさそう auto f1(std::vector<int> vec) -> std::pair<int, std::vector<int>> { return {20, vec}; // コピーされる return {20, std::move(vec)}; // ムーブされる } 20
それでもstd::move()が必要な場合 • return文で関数呼び出ししている場合で、関数呼び出し感がな いもの ➢演算子を適用している場合 • これは特に、ポインタでも必要 auto f(std::optional<std::vector<int>> opt)
-> std::vector<int> { if (!opt) { return {}; } return *opt; // コピーされる return std::move(*opt); // ムーブされる return *std::move(opt); // ムーブされる } 21
まとめ 1. return文のオペランドで関数呼び出しをしていると、NRVO (コピー省略も)が行われなくなる • std::move()も例外ではない 2. return文においてstd::move()をしなくても、ほとんどの場合 暗黙ムーブによってムーブされている •
バージョン毎の差分がややこしい… ➢retrun文においてstd::move()は通常使用する必要は無い ➢C++20以降は特に ➢別の関数呼び出しを伴っている場合は、必要がある場合もある ➢コンストラクタ呼び出しや、*演算子など 22
PR • 株式会社T2ではC++プログラマを積極採用して います! • 自動運転の会社です • C++17でプログラミングできます!! • カジュアル面談から受け付けています!!!
• https://t2.auto/recruit/ 23