我正在读这篇文章:什么是移动语义?
请注意,移动构造函数的帖子中给出的示例是:
string(string&& that) { data = that.data; that.data = nullptr; }
当我们string a(x+y)
用来构造一个新的字符串时,我发现它很混乱.由于结果x+y
是一个临时变量,它很快就会被破坏.这意味着复制指针(data = that.data
)确实会复制一个悬空指针,原始数据(应该存储在x+y
函数调用完成后清理的堆栈帧中)被销毁.似乎设置that.data
为nullptr无济于事,因为堆栈框架无论如何都会被清理干净.
任何人都可以解释为什么这不是一个问题?c ++如何实际处理这种情况?
当你这样做时:
string a(x + y);
它相当于:
string temp(x + y); string a(move(temp)); //destroy temp
您引用的移动构造函数的相关代码采用a
as this
和that
as temp
,因此可以将其内联为:
string temp(x + y); string a(/*uninitialized*/); a.data = temp.data; temp.data = nullptr; //destroy temp
正如你所看到的那样,temp.data
那个被取消的那个,所以析构函数temp
变成了无操作,实际的数据在里面存活a
,正如预期的那样.
看起来你的困惑来自于它的起源data
.在最简单的string
实现中,string::data
始终是动态分配的内存块:
string(const char *str) { size_t len = strlen(str); data = new char[len + 1]; strcpy(data, len); } ~string() { delete[] data; }
即使string
被分配在堆栈,如temp
和a
,甚至x
和y
他们的data
内存块是动态的.
真实的,实际的string
实现通常进行非动态短字符串优化.但是如果你这样做,那么移动构造函数(以及任何其他成员函数)将会更复杂一些.