vector pushback在c++11中移动了一个局部var,测试和混淆
vector push_back a moved local var in c++11 , test and confuse
以下测试在g++4.8.1 中编译
int main()
{
vector<string> v ;
v.push_back("33333") ;
v.push_back("44444") ;
v.push_back("55555") ;
{
string x("xxxxx") ;
v.push_back(x) ; //copy
cout << "x=" << x << endl ; //x=xxxxx
} //checkpoint1
{
string y("yyyyy") ;
v.push_back(std::move(y)) ; //move
cout << "y=" << y << endl ; //y=
} //checkpoint2
for(auto const i : v)
cout << i << " " ;
cout << endl ; //33333 44444 55555 xxxxx yyyyy
}
这是一个非常简单的来源,我的测试重点是std::move
。如您所见,string x
是局部var,而执行v.push_back(x)
时,x
被复制到向量v
,因此x
在push_back
之后仍然有"xxxxx"
。在检查点1之后,x
消失了(它只是本地的),但向量v
有它的值,因为x
是在执行v.push_back(x)
时复制的,所以它是可以的!!
至于string y
,它被移动到向量v
,因为使用了std::move
,所以您可以参见cout << "y=" << y
显示的是"y="
,而不是"y=yyyyy"
,这是正确的行为。
我没有得到的是,在checkpoint2之后,字符串y
,作为一个本地var,它的生命结束了,因此向量v
作为y
的所有者(因为y
被push_back(std::move(y))
移动到向量v
)应该包含一个无效元素,因为y
作为堆栈本地变量,在检查点2是生命终结!
我很困惑,在检查点2之后,向量v
仍然有"yyyyy"
,y
被移到向量v
,如果向量v
只有一个指针vptr = &y
,由于y
是堆栈内存中的局部var,在它的作用域用完后,堆栈就不见了,所以向量vptr
是无用的,看起来这不是真的!
所以它必须是向量有自己的内存来保持"yyyyy"
在自己的内存中,但如果这是既然是push_back(x)
,为什么还要麻烦std::move(y)
呢?
我错过什么了吗?
您可以将std::string
看作一个智能指针。std::string
变量指向存储在其他地方的实际字符串数据。当您std::move
为std::string
时,会为新字符串提供一个指向该数据的指针,并清除旧字符串。
以下是一个非常简单的工作方式:
class MyString {
public:
// Move constructor
MyString(MyString&& that)
// Just make our string data point to the other string
: string_data(that.string_data)
{
// And make sure the string we are moving from no longer points
// to that data so it won't get freed when the other string
// is destructed.
that.string_data = 0;
}
// Copy constructor
MyString(const MyString& that)
// We can't take the other string's data, so we need a copy
: string_data(new char[strlen(that.string_data)+1])
{
strcpy(string_data,that.string_data);
}
// Assignment using copy and swap idiom.
MyString& operator=(MyString that)
{
std::swap(string_data,that.string_data);
return *this;
}
~MyString()
{
// string_data may be null if it has been moved from, but
// that's ok -- it is safe to delete a null pointer.
delete [] string_data;
}
private:
char *string_data;
};
将y
移动到矢量中时。字符串数据现在是矢量拥有的字符串的一部分,y
不再与它有任何关系。当y
超出范围时,它对矢量中的数据没有影响,因为y
不再有指向它的指针。
移动构造函数与复制构造函数一样,涉及两个对象:(A)原始源对象;以及(b)新创建的目的地对象。
在您的情况下,局部变量是源对象,目标对象是push_back
新创建的对象,该对象放置在矢量存储中。
移动构造函数和复制构造函数之间的区别在于,按照惯例,源对象可能会被修改,并且不希望再次使用(源对象是一个"过期"对象)。这允许类作者进行可能损坏源对象的优化,例如将资源从源对象转移("移动")到目标对象。
在std::string
的情况下,可能每个字符串都包含一个指向动态分配的数组的成员指针。move构造函数可以简单地将指针从源对象交换到目标对象。
- 使用的未初始化局部变量'Quick'
- 修复未初始化的局部变量错误
- 局部变量保留函数中的值
- 为什么 'main' 函数中的局部 int 变量会自动初始化?
- 如何使用 C++ 中的继承函数访问派生类中的局部变量
- 将引用分配给局部变量,如果局部变量超出范围,它会超出范围吗?
- 在 OpenGL 中将笛卡尔世界坐标转换为球面局部坐标
- 使用 getline(cin, var) 两次在进行字符串比较时会产生错误 (==)
- Gnuplot_i.hpp C++接口绘制局部变量而不是文件
- 如何在函数外部访问函数中局部变量的值?
- ( var > x) 和 ( x < var)之间有什么区别吗?
- 赋予全局变量而不是局部变量优先级的函数 - (异常行为)
- C++中静态方法的局部变量范围
- 未初始化的局部变量错误甚至认为我初始化了它(C++)
- 离开范围后如何保护局部变量的值?
- 局部变量名称冲突
- C++ lambda:如何'freeze'局部变量的值?
- 我应该使我的局部变量常量还是可移动的
- 获取具有静态局部变量的绑定/推断捕获 lambda 的函数指针
- vector pushback在c++11中移动了一个局部var,测试和混淆