c++ 临时变量拷贝问题

c++中,一个函数返回临时变量,接收者接受这个返回结果作为变量,会造成几次拷贝呢?



#include<iostream>
using namespace std;

class CopyTrack
{
public:
	CopyTrack() 
    {
      cout << "[CopyTrack::CopyTrack ]" << endl;  
    }
	CopyTrack(const CopyTrack &c)
	{
        i = c.i;
		cout << "[CopyTrack::copy-constructor]" << endl;
	}
	~CopyTrack()
	{
		cout << "[CopyTrack::~CopyTrack]" << endl;
	}
	int i = 0;
};
CopyTrack GetCopy()
{
	CopyTrack c;
	c.i = 5;
	return c;
}
int main()
{
	CopyTrack  c = GetCopy();
	cout << "c.i=" << c.i << endl;
    return 0;
}

按理说,CopyTrack c = GetCopy();这个会导致发生两次拷贝,第1次拷贝发生是GetCopy函数内的临时变量拷贝到结果,第2次是返回结果作为参数生成c。但实际没有发生任何拷贝

root@ubuntu:~/share/test/cpp# g++ copy.cpp 
root@ubuntu:~/share/test/cpp# ./a.out
[CopyTrack::CopyTrack ]
c.i=5
[CopyTrack::~CopyTrack]
root@ubuntu:~/share/test/cpp#

这和编译器有关,修改编译器参数,把相关优化去掉,-fno-elide-constructors,便发生了两次拷贝

root@ubuntu:~/share/test/cpp# g++ -fno-elide-constructors  copy.cpp
root@ubuntu:~/share/test/cpp# ./a.out
[CopyTrack::CopyTrack ]
[CopyTrack::copy-constructor]
[CopyTrack::~CopyTrack]
[CopyTrack::copy-constructor]
[CopyTrack::~CopyTrack]
c.i=5
[CopyTrack::~CopyTrack]
root@ubuntu:~/share/test/cpp#

如何变成一次拷贝呢?
方法一,不用变量名

int main()
{
	//CopyTrack  c = GetCopy();
	//cout << "c.i=" << c.i << endl;
    cout << "c.i=" << GetCopy().i << endl;
    return 0;
}
root@ubuntu:~/share/test/cpp# g++ -fno-elide-constructors  copy.cpp
root@ubuntu:~/share/test/cpp# ./a.out
c.i=[CopyTrack::CopyTrack ]
[CopyTrack::copy-constructor]
[CopyTrack::~CopyTrack]
5
[CopyTrack::~CopyTrack]
root@ubuntu:~/share/test/cpp# 

方法2,用右值引用

int main()
{
	CopyTrack  &&c = GetCopy();
	cout << "c.i=" << c.i << endl;
    //cout << "c.i=" << GetCopy().i << endl;
    return 0;
}
root@ubuntu:~/share/test/cpp# g++ -fno-elide-constructors  copy.cpp
root@ubuntu:~/share/test/cpp# ./a.out
[CopyTrack::CopyTrack ]
[CopyTrack::copy-constructor]
[CopyTrack::~CopyTrack]
c.i=5
[CopyTrack::~CopyTrack]
root@ubuntu:~/share/test/cpp# 

那怎样让其一次拷贝也没有呢?

右值引用的问题
右值引用一个左值不可以,但作为函数参数,右值引用左值却可以。这是因为在普通函数中T &&为右值引用,但在模板参数中T&& 可能是左值引用,也可能是右值引用。模板参数中T &为强制左值引用。

template<typename T>
void Pkg(T &&t)
{
	t.i = 3;
}
int main()
{
	CopyTrack  c = GetCopy();
    CopyTrack && c1 = c;  //error
    Pkg(c); //okay
	cout << "c.i=" << c.i << endl;
    //cout << "c.i=" << GetCopy().i << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值