関数の戻り値で、オブジェクトを返した場合に、そのコピーコンストラクタが呼ばれません。
C++
1#include <iostream> 2 3class CBase { 4public: 5 CBase(int data); 6 CBase(const CBase& base); 7 void operator=(const CBase& base); 8 virtual ~CBase(); 9 10private: 11 int m_data; 12}; 13 14CBase::CBase(int data) : m_data(data) { 15 std::cout << "CBase::CBase(): " << m_data << std::endl; 16} 17 18CBase::CBase(const CBase& base) { 19 std::cout << "CBase::CBase(const CBase& base): " << m_data << std::endl; 20} 21 22void CBase::operator=(const CBase& base) { 23 std::cout << "void CBase::operator=(const CBase& base): " << m_data << std::endl; 24} 25 26CBase::~CBase() { 27 std::cout << "CBase::~CBase(): " << m_data << std::endl; 28} 29 30CBase Create() { 31 CBase base(2); 32 return base; 33} 34 35int main() { 36 CBase base(1); 37 base = Create(); 38 std::cout << "End" << std::endl; 39}
実行結果 CBase::CBase(): 1 CBase::CBase(): 2 void CBase::operator=(const CBase& base): 1 CBase::~CBase(): 2 End CBase::~CBase(): 1
Create関数でCBaseのインスタンスbaseを返していますが、実際には、baseが戻り値のテンポラリオブジェクトにコピーされ、それが返されます。
そのため、実行結果の4行目に、テンポラリオブジェクトのデストラクタが呼ばれています。
しかしそれならば、「CBase テンポラリオブジェクト = base」の初期化が行われているはずなので、コピーコンストラクタが呼ばれると思うのですが、呼ばれていません。
ここで、CBaseのコピーコンストラクタをprivateにして呼び出し禁止にすると、コンパイルエラーが発生します。
これは、コピーコンストラクタを呼び出す建前で構文はチェックされるが、最適化でコピーコンストラクタが呼ばれない形でオブジェクトが返されているということなのでしょうか。
ここから、関連した質問です。
上記の仮説が正しいとすると、最適化が行われない場合、以下のコードは戻り値のテンポラリオブジェクトをテンポラリオブジェクトで初期化して、それを返していることになり、2つ分のデストラクタが呼ばれることになるのでしょうか。
C++
1CBase Create() { 2 return CBase(2); 3}
また、Create関数で定義したCBase base(2);は、ローカル変数なので、Create関数を抜けたとき(operator=が呼ばれる前)に、デストラクタが呼ばれると思うのですが、なぜ呼ばれないのでしょうか。
(予想としては、戻り値のテンポラリオブジェクトをbaseで初期化せず、baseをテンポラリオブジェクトとして直接返しているから?)
以上、宜しくお願い致します。

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/02/01 11:06