【发布时间】:2017-08-21 14:05:20
【问题描述】:
请考虑以下代码:
struct MyStruct
{
int iInteger;
string strString;
};
void MyFunc(vector<MyStruct>& vecStructs)
{
MyStruct NewStruct = { 8, "Hello" };
vecStructs.push_back(std::move(NewStruct));
}
int main()
{
vector<MyStruct> vecStructs;
MyFunc(vecStructs);
}
为什么会这样?
在调用 MyFunc 的那一刻,返回地址应该放在当前线程的栈上。现在创建 NewStruct 对象被创建,它也应该放在堆栈上。通过 std::move,我告诉编译器,我不打算再使用 NewStruct 引用。他可以窃取记忆。 (push_back 函数是具有移动语义的函数。)
但是当函数返回并且 NewStruct 超出范围时。即使编译器不会从堆栈中移除原来存在的结构所占用的内存,他至少也必须移除之前存储的返回地址。
这会导致堆栈碎片化,未来的分配会覆盖“移动”的内存。
谁能给我解释一下,好吗?
编辑: 首先:非常感谢您的回答。 但是根据我所学到的,我仍然无法理解,为什么以下内容不能像我期望的那样工作:
struct MyStruct
{
int iInteger;
string strString;
string strString2;
};
void MyFunc(vector<MyStruct>& vecStructs)
{
MyStruct oNewStruct = { 8, "Hello", "Definetly more than 16 characters" };
vecStructs.push_back(std::move(oNewStruct));
// At this point, oNewStruct.String2 should be "", because its memory was stolen.
// But only when I explicitly create a move-constructor in the form which was
// stated by Yakk, it is really that case.
}
void main()
{
vector<MyStruct> vecStructs;
MyFunc(vecStructs);
}
【问题讨论】:
-
除了
main应该返回int,你的例子很好。移动构造只是将NewStruct的状态 移动到vecStructs中的新元素。新元素与NewStruct不同,两者的生命周期都与对方的生命周期没有任何关系。考虑使用std::vector::emplace_back而不是push_back。 -
移动语义不会“删除”“堆栈上的插槽”。从(在您的示例中为
NewStruct)移动的对象保证存在,尽管处于“未指定但可用状态”。 -
std::move什么都不做,只是一个演员表:stackoverflow.com/questions/21358432/… -
move更像是将所有资金从一个银行账户转移到另一个银行账户,而不是将银行账户转移给新所有者。
标签: c++ c++11 move move-semantics