[英]std::move and construction/destruction of objects
我记得,在调用任何函数之前,它会在堆栈中为函数结果和参数分配内存。 这是否意味着我有
T func()
{
T a;
return std::move(a);
}
我仍将进行复制,因为已经为整个T分配了内存? 我也读过类似的问题
return a;
与...相同
return std::move(a);
所以,我无法避免复制到堆栈? rvalue是堆栈中的值吗?
这是在某个地方使用它的好方法吗?
T a = std::move(func());
所以我会避免复制函数的结果? 我仍然需要创建特殊的move构造函数和move operator =吗?
我试图对其进行测试并得到:
class Temp
{
public:
Temp()
{
cout << "construct" << endl;
i = 5;
}
~Temp()
{
cout << "destruct" << endl;
}
Temp(const Temp& t)
{
i = t.i;
cout << "copy construct" << endl;
}
Temp operator=(const Temp& t)
{
i = t.i;
cout << "operator =" << endl;
return *this;
}
int i;
};
Temp tempfunc1()
{
Temp t1;
t1.i = 7;
return t1;
}
Temp tempfunc2()
{
Temp t1;
t1.i = 8;
return std::move(t1);
}
int main()
{
Temp t1;
Temp t2;
t2.i = 6;
t1 = t2;
cout << t1.i << endl;
t1.i = 5;
t1 = std::move(t2);
cout << t1.i << endl;
cout << "NEXT" << endl;
t1 = tempfunc1();
cout << t1.i << endl;
cout << "NEXT" << endl;
t1 = std::move(tempfunc1());
cout << t1.i << endl;
cout << "NEXT" << endl;
t1 = tempfunc2();
cout << t1.i << endl;
cout << "NEXT" << endl;
t1 = std::move(tempfunc2());
cout << t1.i << endl;
}
结果:
construct
construct
operator =
copy construct
destruct
6
operator =
copy construct
destruct
6
NEXT
construct
copy construct
destruct
operator =
copy construct
destruct
destruct
7
NEXT
construct
copy construct
destruct
operator =
copy construct
destruct
destruct
7
NEXT
construct
copy construct
destruct
operator =
copy construct
destruct
destruct
8
NEXT
construct
copy construct
destruct
operator =
copy construct
destruct
destruct
8
好像使用std :: move没有任何作用。 还是仅在存在特定构造函数和析构函数的情况下有效?
为什么“ t1 = t2”同时调用复制构造函数和operator =?
抱歉,我问了这么多问题,这些问题可能非常简单,即使在阅读了很多有关此问题之后,也许是因为我的英语不好,我仍然需要解释。
先感谢您。
我对您的代码进行了一些更改,这些更改可能有助于您理解和探索所有工作原理。 我向每个Temp
对象添加了一个id
元素,以使其更容易理解哪个对象,并且还更改了operator=
的签名以返回引用而不是对象。 首先,这是使其成为完整程序所需的include
:
#include <iostream>
using std::cout;
using std::endl;
接下来,这是现在包含std::move
构造函数(带有&&
)和move =运算符的类:
class Temp
{
int id;
public:
Temp() : id(++serial), i(5)
{
cout << "construct " << id << endl;
}
~Temp()
{
cout << "destruct " << id << endl;
}
Temp(const Temp& t) : id(++serial), i(t.i)
{
cout << "copy construct " << id << " from " << t.id << endl;
}
Temp(Temp &&t) : id(++serial), i(t.i)
{
t.i = 5; // set source to a default state
cout << "move construct " << id << " from " << t.id << endl;
}
Temp &operator=(const Temp& t)
{
i = t.i;
cout << "operator = " << id << " from " << t.id << endl;
return *this;
}
Temp &operator=(Temp&& t)
{
i = t.i;
t.i = 5; // set source to a default state
cout << "move operator = " << id << " from " << t.id << endl;
return *this;
}
int i;
static int serial;
};
int Temp::serial = 0;
您的功能仍然相同,但请参阅注释
Temp tempfunc1()
{
Temp t1;
t1.i = 7;
return t1;
}
Temp tempfunc2()
{
Temp t1;
t1.i = 8;
return std::move(t1); // not necessary to call std::move here
}
我对main()
进行了些微改动,以显示其全部工作原理:
int main()
{
Temp t1;
Temp t2;
t2.i = 6;
t1 = t2;
cout << t1.i << endl;
t1.i = 5;
t1 = t2;
cout << t1.i << endl;
cout << "NEXT" << endl;
t1 = tempfunc1();
cout << t1.i << endl;
cout << "NEXT" << endl;
t1 = std::move(tempfunc1());
cout << t1.i << endl;
cout << "NEXT" << endl;
t1 = tempfunc2();
cout << t1.i << endl;
cout << "NEXT" << endl;
Temp t3(tempfunc1());
cout << t3.i << endl;
cout << "NEXT" << endl;
Temp t4(t1);
cout << t4.i << endl;
}
最后是输出:
construct 1
construct 2
operator = 1 from 2
6
operator = 1 from 2
6
NEXT
construct 3
move operator = 1 from 3
destruct 3
7
NEXT
construct 4
move operator = 1 from 4
destruct 4
7
NEXT
construct 5
move construct 6 from 5
destruct 5
move operator = 1 from 6
destruct 6
8
NEXT
construct 7
7
NEXT
copy construct 8 from 1
8
destruct 8
destruct 7
destruct 2
destruct 1
如您所见,使用fixed operator=
,不会创建任何临时文件。 同样,一旦提供了operator=
的移动版本,临时对象(与tempfunc1()
和tempfunc2()
函数返回的对象一样)将自动使用移动语义。 您的tempfunc2()
实际上并不需要std::move
调用。 如您所见,这只会产生另一个临时性,因此带来的伤害大于帮助。 最后请注意,在创建t3
,只创建了一个对象,不需要临时或move
构造函数。
值得注意的是,在这个琐碎的类中,move构造函数实际上并没有多大帮助,但是对于使用分配的内存或创建计算量很大的类,它可以提供很多帮助。 在这种情况下,记住移动构造函数(或在operator=
的移动版本中)需要多个步骤是很有用的。 具体来说,您必须:
nullptr
以便析构函数可以正确运行),最后, *this
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.