C++のコピー省略(Copy Elision)とRVO(戻り値の最適化)とは?仕組みをサンプルコードで解説
コピー省略(Copy Elision)は「コピーの省略」とも呼ばれる、コンパイラが行う最適化技術の一つです。オブジェクトの不要なコピーを回避することで、プログラムの実行効率を向上させます。現在の主要なC++コンパイラのほとんどが、この最適化技術を採用しています。
また、関数の戻り値に対して同様の最適化を適用する仕組みは、RVO(Return Value Optimization:戻り値の最適化)と呼ばれます。
それでは、サンプルコードを使って、コピー省略がどのように動作するのかを見ていきましょう。
サンプルコード
#include <iostream>
using namespace std;
class MyClass {
public:
MyClass(const char* str = "\0") { //デフォルトコンストラクタ
cout << "Constructor called" << endl;
}
MyClass(const MyClass &my_cls) { //コピーコンストラクタ
cout << "Copy constructor called" << endl;
}
};
main() {
MyClass ob = "copy class object";
}実行結果
Constructor called
なぜコピーコンストラクタが呼ばれないのか?
ここで注目すべきは、実行結果に「Copy constructor called」が表示されていない点です。つまり、コピーコンストラクタが呼び出されていません。
通常、オブジェクトを初期化する際には、一時オブジェクト(テンポラリオブジェクト)が生成され、それが実際のオブジェクトへコピーされるという手順が踏まれます。内部的には、次のように動作していると考えることができます。
MyClass ob = "copy class object";
上記のコードは、実際には以下のように解釈されます。
MyClass ob = MyClass("copy class object");もしコピー省略が行われなければ、一時オブジェクトの生成後にコピーコンストラクタが呼び出され、実行結果には「Copy constructor called」も表示されるはずです。
しかし、C++コンパイラはこのような余分なオーバーヘッドを検出し、一時オブジェクトの生成とコピーの処理を省略して、オブジェクトを直接構築します。これがコピー省略の仕組みです。
補足:C++17以降の保証されたコピー省略
C++17以降では、一時オブジェクトに対するコピー省略は標準規格によって保証されるようになりました(必須のコピー省略)。そのため、コピーコンストラクタやムーブコンストラクタが削除されたクラスであっても、上記のような初期化が可能になっています。
-
【C++】前置インクリメント「++i」と後置インクリメント「i++」の違いとは?
C++のインクリメント演算子「++」には、前置(prefix)と後置(postfix)の2つの形式があり、それぞれ動作に大きな違いがあります。前置インクリメント(++i):変数 i の値を先に1増やし、その増加後の新しい値が式の値になります。つまり、「まず増加してから値を返す」動作です。後置インクリメント(i++):変数 i の値は1増やされますが、式の値としては増加前の元の値が使われます。つまり、「まず値を返してから増加する」動作です。サンプルコード実際のコードを見ながら、その違いを詳しく確認してみましょう。#include<iostream> using namespace s
-
C++のsigned(符号付き)とunsigned(符号なし)キーワードとは?違いと使い方を解説
C++における符号付き・符号なしデータ型の基本C++では、すべての数値型に対して「符号付き(signed)」か「符号なし(unsigned)」かを指定できます。たとえば、int型を宣言する際に正の整数のみを扱うよう指定することも可能です。特別な指定がない場合、すべての整数型はデフォルトで符号付き(signed)として扱われます。つまり、正負どちらの値も保持できるということです。一方、unsignedキーワードを使用すると、符号を持たない変数を宣言できます。サンプルコード#include<iostream>using namespace std;int main() { &