函数返回语句与copy (move) constructor, copy (move) assignment operator的关系

考察下面的函数:

// This program is designed to test the relationship between the 
// return statements and the copy (move) constructors.
#include <iostream>
#include <vector>
#include <string>

using namespace std;

class IntCell
{
public:
	IntCell(int num = 0) :m_iNum(num)
	{
		cout << "\nInt-parameter constructor called.\n";
	}
	// Copy constructor
	IntCell(const IntCell & rhs) :m_iNum(rhs.m_iNum)
	{
		cout << "\nThe copy constructor called.\n";
	}
	// Move constructor
	IntCell(IntCell && rhs) :m_iNum(std::move(rhs.m_iNum))
	{
		cout << "\nThe move constructor called.\n";
	}
	// Copy assignment operator
	IntCell& operator=(const IntCell& rhs)
	{
		cout << "\nThe copy assignment operator called.\n";
		if (this != &rhs)
			m_iNum = rhs.m_iNum;

		return *this;
	}
	// Move assignment operator
	IntCell& operator=(IntCell&& rhs)
	{
		cout << "\nThe move assignment operator called.\n";
		std::swap(m_iNum, rhs.m_iNum);
		return *this;
	}

	IntCell operator+(const IntCell & rhs)
	{
		IntCell sum;
		sum.m_iNum = m_iNum + rhs.m_iNum;
		return sum;
	}
private:
	int m_iNum;
};

IntCell func1(int n)
{
	IntCell temp{ n };
	return temp;
}

IntCell func2(int n)
{
	return IntCell(n);
}

IntCell& firstItem(vector<IntCell> & IntCellVec)
{
	cout << "\nNon-const version of firstItem called.\n";
	return IntCellVec[0];
}

const IntCell& firstItem(const vector<IntCell> & IntCellVec)
{
	cout << "\nConst version of firstItem called.\n";
	return IntCellVec[0];
}

void separation( )
{
	cout << "\n------------------------------------------------------\n";
}

int main( )
{
	int num = 12;
	cout << "\nThe functions invoked by\nfunc1(num);\n";
	func1(num);
	separation( );
	cout << "\nThe functions invoked by\nfunc2(num);\n";
	func2(num);
	separation();
	cout << "\nThe functions invoked by\nIntCell myIntCell (func1(num));\n";
	IntCell myIntCell (func1(num));
	separation();
	cout << "\nThe functions invoked by\nIntCell yourIntCell(myIntCell);\n";
	IntCell yourIntCell(myIntCell);
	separation();
	cout << "\nThe functions invoked by\nIntCell hisIntCell(std::move(myIntCell));\n";
	IntCell hisIntcell(std::move(myIntCell));
	separation( );

	vector<IntCell> myIntCellVec;
	myIntCellVec.push_back(IntCell(1));
	myIntCellVec.push_back(IntCell(2));
	myIntCellVec.push_back(IntCell(3));

	IntCell addent(2);
	IntCell result;
	separation();
	cout << "\nThe functions invoked by\n" << "IntCell& rsl = firstItem(myIntCellVec);\n";
	IntCell& rsl = firstItem(myIntCellVec);
	separation();
	cout << "\nThe functions invoked by\n" << "result = firstItem(myIntCellVec);\n";
	result = firstItem(myIntCellVec);
	separation();
	cout << "\nThe functions invoked by\n" << "result = firstItem(myIntCellVec) + addent;\n";
	
	result = firstItem(myIntCellVec) + addent;
	system("pause");
}

上述代码在Visual Studio2013环境下的运行结果是:

The functions invoked by
func1(num);
 
Int-parameter constructor called.
 
The move constructor called.
 
------------------------------------------------------
 
The functions invoked by
func2(num);
 
Int-parameter constructor called.
 
------------------------------------------------------
 
The functions invoked by
IntCell myIntCell (func1(num));
 
Int-parameter constructor called.
 
The move constructor called.
 
------------------------------------------------------
 
The functions invoked by
IntCell yourIntCell(myIntCell);
 
The copy constructor called.
 
------------------------------------------------------
 
The functions invoked by
IntCell hisIntCell(std::move(myIntCell));
 
The move constructor called.
 
------------------------------------------------------
 
……
 
------------------------------------------------------
 
The functions invoked by
IntCell& rsl = firstItem(myIntCellVec);
 
Non-const version of firstItem called.
 
------------------------------------------------------
 
The functions invoked by
result = firstItem(myIntCellVec);
 
Non-const version of firstItem called.
 
The copy assignment operator called.
 
------------------------------------------------------
 
The functions invoked by
result = firstItem(myIntCellVec) + addent;
 
Non-const version of firstItem called.
 
Int-parameter constructor called.
 
The move constructor called.
 
The move assignment operator called.

下面我们来逐一分析之。

一,

The functions invoked by
func1(num);
 
Int-parameter constructor called.
 
The move constructor called.
 
------------------------------------------------------

之所以会调用move constructor,是因为……你记住它就行了。有的编译器不会调用。不过在写代码的时候不要做出过于乐观的估计。

二,

The functions invoked by
func2(num);
 
Int-parameter constructor called.
 
------------------------------------------------------

之所以这次没有调用move constructor,是因为编译器进行了优化。同样,写代码的时候不要做出过于乐观的估计。

三,

The functions invoked by
IntCell myIntCell (func1(num));
 
Int-parameter constructor called.
 
The move constructor called.
 
------------------------------------------------------

这个没啥可说的。

四,

The functions invoked by
IntCell yourIntCell(myIntCell);
 
The copy constructor called.
 
------------------------------------------------------

这个也没啥可说的。

五,

The functions invoked by
IntCell hisIntCell(std::move(myIntCell));
 
The move constructor called.
 
------------------------------------------------------

同样,没啥可说的。

 

六,

------------------------------------------------------
 
The functions invoked by
IntCell& rsl = firstItem(myIntCellVec);
 
Non-const version of firstItem called.

这个语句调用的函数出人意料地少。这是因为参数的传递及返回都是通过reference来实现的。

七,

------------------------------------------------------
 
The functions invoked by
result = firstItem(myIntCellVec);
 
Non-const version of firstItem called.
 
The copy assignment operator called.

虽然firstItem函数返回的是引用,但是如果没有合理利用这一点的话,还是会调用copy assignment operator的。

八,

------------------------------------------------------
 
The functions invoked by
result = firstItem(myIntCellVec) + addent;
 
Non-const version of firstItem called.
 
Int-parameter constructor called.
 
The move constructor called.
 
The move assignment operator called.
这里调用了Int-parameter constructor是因为 operator+里构造了sum对象,后面的moveconstructor被调用是因为operator+是按值返回的。最后的move assignment operator被调用是因为operator+按值返回的对象是右值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值