プログラミング
std::moveなしでC++を移動する
Move in C++ without a std:move (andreasfertig.com)
要約
C++において、不要なコピー操作はパフォーマンスの敵であり、return value optimization (RVO) や named return value optimization (NRVO) がコピーを省略する上で重要である。C++11以降、暗黙的な移動(implicit move)も導入されたが、特定のケースでは手動でのstd::moveが必要だった。しかし、C++23ではこれらのケースでも暗黙的な移動が行われるようになり、std::moveを稀にしか使わないという原則をさらに強く支持する。
全文翻訳
std::moveなしでC++を移動する
以前の投稿「なぜstd::moveはめったに使うべきではないのか」で、std::moveはめったに使うべきではないと述べました。今日の投稿では、このアドバイスの利点、つまりデフォルトで最高のパフォーマンスを示す方法を紹介したいと思います。
Return Value Optimization
パフォーマンスにとって最悪の敵の一つは、不要なコピー操作です。Return Value Optimization (RVO) についてはきっと聞いたことがあるでしょう。これは、可能であれば常に目指すべきものです。RVOとは、返されるオブジェクトが関数内のスタック上に作成されるのではなく、値が最終的に配置される呼び出し側で作成されることを意味します。これにより、コピーと移動が節約されます。標準では、これをコピーエリジョン(copy elision)と参照しており、標準はコンパイラの最適化については決して言及しません。
C++17以降、以下のケースではコピーエリジョンが保証されます。
```cpp
Apple RVO() {
return {};
}
```
これは純粋なRVOです。次に、Named Return Value Optimization (NRVO) があります。
```cpp
Apple NRVO() {
Apple res{};
return res;
}
```
後者は保証されたコピーエリジョンの対象ではありません。おそらく、そこでもコピーや移動のコストはかからないでしょう。
コピーの代わりに移動する
コピーエリジョンの次に良いのは、オブジェクトを移動することです。C++11以降、言語には暗黙的な移動が発生する場所がいくつかありました。
```cpp
Apple Fun(Apple val) {
return val;
}
```
このコードでは、結果のオブジェクトはパラメータから移動されます。
このコンテンツは気に入りましたか?
私は世界中で、オンサイトまたはリモートで、社内C++トレーニングクラスを提供しています。私のクラスのサンプルリストを以下に示します。
* CからC++へ
* C++11からC++17でのプログラミング
* C++20でのプログラミング
すべてのクラスは、チームのニーズに合わせてカスタマイズできます。
トレーニングサービス
しかし、言語にはもう少し複雑なケースもありました。私が共有したい最初の例は次のとおりです。
```cpp
Apple Cat(Apple&& val) {
return val;
}
```
ここでは、rvalue参照パラメータを受け取る関数があり、受け取ったオブジェクトを返しています。このコードはコンパイルされますが、C++20より前では、戻り値のコピー構築が発生していました。まあ、GCCのような標準に準拠したコンパイラではそうです。あまり準拠していないClangコンパイラは、ムーブ構築を提供します。はい、時にはルールに従わない方が良いこともあります。
私がより嫌っていたもう一つの例は次のとおりです。
```cpp
Apple Cat(Apple&& val) {
return val;
}
```
ここでもrvalue参照パラメータを受け取る関数がありますが、今回はrvalue参照が返されます。今回は、戻り値を手動で移動しないとコードはコンパイルされません。これは私の(めったに使わないstd::moveの)アドバイスに反します。
公平を期すために言うと、両方のケースで最良の結果を得るには、戻り値を移動することが必要です。したがって、両方のケースが私の(めったに使わないstd::moveの)アドバイスに反します。
コンパイラをC++23モードに切り替えると、両方のケースで暗黙的な移動が行われます。std::moveは不要になります。これで、std::moveをさらに稀にしか使わないという私のルールに従うことができます!
アンドレアス
C++ Insights エピソード77: RVO、NRVO、std::move解説 »
最近の投稿
std::moveなしでC++を移動する
2026年9月1日
C++ Insights エピソード77: RVO、NRVO、std::move解説
2026年8月19日
std::nullptr_t でより多くのコンパイル時チェック
2026年8月4日