何度もお世話になっております。
質問の間隔が短くてすみません、なるべく自分一人で解決したいのですが疑問が解けずにトピックを立ててしまいました。
私の環境は Visual Studio C++ 2010 でございます。
質問の内容ですが、以下のようなコードで
► スポイラーを表示
コード:
#include <iostream>
#include <memory>
using namespace std;
/* 関数テンプレートの作成対象になるクラステンプレート */
template<typename T> class MyClass{
public:
MyClass(T num){ m_number = num; cout << "コンストラクタが呼ばれました" << endl; }
MyClass(MyClass& rOpe){ cout << "コピーコンストラクが呼ばれました" << endl; this->m_number = rOpe.m_number; }
~MyClass(){ cout << "デストラクタが呼ばれました" << endl; }
MyClass& operator=(const MyClass& ope){ cout << "代入演算子が呼ばれました" << endl; this->m_number = ope.m_number; return *this; }
private:
T m_number;
};
/* MyClassクラスのオブジェクトを作って返すだけの関数テンプレート */
template<typename T> MyClass<T> create_MyCls(T num){
MyClass<T> tmp(num);
return tmp; //一時オブジェクトをコピーコンストラクタで初期化
}
/* unique_ptrクラスのオブジェクトを作って返すだけの関数テンプレート */
template<typename T>
unique_ptr<MyClass<T> > create_uPtr(T num){
unique_ptr<MyClass<T> > tmp( new MyClass<T>(num) );
return tmp; //一時オブジェクトをムーブコンストラクタで初期化?
}
int main(){
unique_ptr< MyClass<int> > u_obj = create_uPtr(100);
MyClass<int> m_obj(10);
m_obj = create_MyCls(50); //代入演算子が呼ばれる
return 0;
}
クラスのオブジェクトを作って、そのまま return する関数が2つあります。
ムーブコンストラクタを定義していない普通のクラス(MyClass)のオブジェクトを作り、returnする際には
1. 引数1つのコンストラクタを呼び出す
2. 関数のreturn文のところで一時オブジェクトを作成して、コピーコンストラクタで初期化
3. 呼び出し元へ戻り、定義した代入演算子が呼ばれて、オブジェクトにその内容がコピーされる
という順番に処理が行われると思うのですが、一方で unique_ptrクラスを作る関数では
同じく関数内部でオブジェクトが作られて return する際に、ムーブコンストラクタが呼ばれているようです。
ここで疑問に思ったのですが、関数内部で作られるオブジェクトは、この場合は左辺値であって
右辺値参照を引数にとる、ムーブコンストラクタが呼ばれるのは何故なのだろうということです。
戻り値最適化が行われていて、return文のところで行われる一時オブジェクトの生成(?)が省略されている所為なのかとも考えたのですが、
それならば最適化が行われなかったときはどうなるのか、という疑問もあります。(コピーコンストラクタは unique_ptr クラスでは隠ぺいされているので呼べないと思いますし)
そもそも、オブジェクトが return されるときの挙動を私が勘違いしている所為かもしれませんが、いまいち理解できません。
どうか、よろしくお願いします。