详解CPP中的按值传递的函数调用问题

按值传递

按值传入

C中传参方法就两个,一个是按值传递,一个是传指针。CPP当然也继承了它爹C的性质。不过按值传递是怎么个传递法,在CPP中又是个什么情况,很多人都没搞明白,下面我们来看看,类的按值传递问题

//使用全局变量记录生成个数,让运行更清晰
int buildcont = 0;

//按值传递测试
struct test
{
	int a;
	test() { a = buildcont++; cout << "test"<<a<<"  is build!" << endl; }
	test(const test& other) { a = buildcont++; cout << "test" << a << "  is build by copy!" << endl; }
	//移动构造函数
	 //test(test&& other)noexcept { a = buildcont++; cout << "test" << a << "  is build by movebild" << endl; }
	~test(){ cout << "test "<<a <<"  is destory!" << endl; }
};

void testfun1(test aint)
{
	return;
}

int main()
{
	test test0;
	cout << "------------" << endl;
	testfun1(test0);
	cout << "------------" << endl;
	return 0;
}

运行结果

test0  is build!
------------
test1  is build by copy!
test 1  is destory!
------------
test 0  is destory!

  • 第一个build是我们test test0;
  • void testfun1(test aint)当你按值把对象传到函数里面去,实际上,是调用了一次拷贝构造函数,生成了一个函数栈内存中的test对象test1(镜像一下,一般不影响原值(如果你的拷贝构造函数是正常的话))
  • 函数运行结束,自动调用析构函数,报出test1销毁。返回主函数
  • 主函数运行到return 0;自动销毁所有对象,test0的析构被调用,程序结束

按值传出

test testfun2(test aint)
{
	cout << "-----tag here-----" << endl;
	return aint;
}

int main()
{
	test test0;
	cout << "------------" << endl;
	testfun2(test0);
	cout << "------------" << endl;
	return 0;
}

运行结果

test0  is build!
------------
test1  is build by copy!
-----tag here-----
test2  is build by movebild
test 1  is destory!
test 2  is destory!
------------
test 0  is destory!

分析

  • test1 is build by copy!这是按值传递,拷贝构造运行,将test0的副本(记为test1)加入函数testfun2的栈中
  • -----tag here-----函数体运行的结果
  • test2 is build by copy!这句话是**return aint;**的运行结果,实质是将栈中的test1做返回值。但是函数栈要被销毁(运行到结尾了),所以再次调用拷贝构造函数,把test1的副本传到主函数中(这是一个无名变量,记为test2)
    • 指出,这里如果不写移动构造函数确实是copy,如果写了那就是调用移动构造函数,报为:test2 is build by movebuildCPP会自动选择最有利的构造函数
  • test1 is destory!这第一个销毁,销毁的是test1,它在testfun2的栈中,函数运行完成,分配的栈内存被回收,自然被销毁
  • test2 is destory!这第二个销毁,销毁的是返回到主函数中的无名对象(test2),因为它的生命只在testfun2(test0);这个语句,运行到下一个语句的时候test2就被销毁了(不理解?看看下一个例子)。

移动构造

移动构造函数是C11提出的特性,它的特点是把无名变量的资源重新利用生成具名对象,而无需再次从0构造,让CPP更快,下面是函数格式

 test(test&& other)noexcept { 
 a = buildcont++; 
 cout << "test" << a << "  is build by movebild" << endl; }

下面是C中常见的新手的写法,基本上都是按值传递,我们可以看看运行结果,不必要的构造了几个对象

int main()
{
	test test0;
	cout << "------------" << endl;
	test temp=testfun2(test0);
	cout << temp.a << endl;
	cout << "------------" << endl;
	return 0;
}

运行结果

test0  is build!
------------
test1  is build by copy!
-----tag here-----
test2  is build by movebild
test 1  is destory!
2
------------
test 2  is destory!
test 0  is destory!
  • test2 is build by movebild这个语句是test temp=testfun2(test0);在主函数中的运行结果,它这里直接把test1的值移动给temp(这里应该有一步优化)
  • 可见,CPP如果按值传递,没有优化的话,要多损耗两个对象的性能(VS 会优化为损耗1个对象的性能,就是拷贝到函数的栈的性能【这是最基本的性能损耗了】)
  • 21
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值