使用unique_ptr移动语义 [英] Move Semantics with unique_ptr
问题描述
我正在使用Visual Studio 2012 Update 2,并且在尝试理解为什么std :: vector试图使用unique_ptr的副本构造函数时遇到麻烦.我看过类似的问题,并且大多数都与没有显式的移动构造函数和/或运算符有关.
如果将成员变量更改为字符串,则可以验证是否调用了move构造函数;但是,尝试使用unique_ptr会导致编译错误:
错误C2248:'std :: unique_ptr< _Ty> :: unique_ptr':无法访问在类'std :: unique_ptr< _Ty>''中声明的私有成员.
我希望有人可以指出我所缺少的内容,谢谢!
#include< vector>#include< string>#include< memory>MyObject类{上市:MyObject():ptr(std :: unique_ptr< int>(新int)){}MyObject(MyObject&& other):ptr(std :: move(other.ptr)){}MyObject&运算符=(MyObject&& other){ptr = std :: move(other.ptr);返回* this;}私人的:std :: unique_ptr< int>ptr;};int main(int argc,char * argv []){std :: vector< MyObject>s;对于(int i = 0; i< 5; ++ i){MyObject o;s.push_back(o);}返回0;}
push_back()
函数按值接受参数.因此,试图复制构造 push_back()
的参数(如果您传递左值),或者尝试移动构造它(如果您传递右值).>
在这种情况下, o
是左值-因为命名对象是左值-并且右值引用不能绑定到左值.因此,编译器无法调用您的move构造函数.
要移动对象 ,您必须编写:
s.push_back(std :: move(o));//^^^^^^^^^^
在这种情况下令我感到惊讶的是,似乎VC11隐式为 MyObject
生成了一个复制构造函数,而没有将其定义为 deleted (根据您发布的错误来判断).情况并非如此,因为您的类声明了move构造函数.实际上,根据C ++ 11标准的第12.8/7段:
如果类定义未显式声明一个副本构造函数,则隐式声明一个副本构造函数.如果上课定义声明了移动构造函数或移动赋值运算符,即隐式声明的副本构造函数定义为已删除;否则,将其定义为默认值(8.4)
我必须得出结论,虽然您得到的错误是正确的-因为您没有将右值传递给 push_back()
-VC11在这里并不完全兼容.
I am using Visual Studio 2012 Update 2 and am having trouble trying to understand why std::vector is trying to use the copy constructor of unique_ptr. I have looked at similar issues and most are related to not having an explicit move constructor and/or operator.
If I change the member variable to a string, I can verify that the move constructor is called; however, trying to use the unique_ptr results in the compilation error:
error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'
.
I'm hoping someone can point me to what I am missing, thanks!
#include <vector>
#include <string>
#include <memory>
class MyObject
{
public:
MyObject() : ptr(std::unique_ptr<int>(new int))
{
}
MyObject(MyObject&& other) : ptr(std::move(other.ptr))
{
}
MyObject& operator=(MyObject&& other)
{
ptr = std::move(other.ptr);
return *this;
}
private:
std::unique_ptr<int> ptr;
};
int main(int argc, char* argv[])
{
std::vector<MyObject> s;
for (int i = 0; i < 5; ++i)
{
MyObject o;
s.push_back(o);
}
return 0;
}
The push_back()
function takes its argument by value. Therefore, an attempt is made to either copy-construct the argument of push_back()
(if you are passing an lvalue), or to move-construct it (if you are passing an rvalue).
In this case, o
is an lvalue - because named objects are lvalues - and rvalue references cannot bind to lvalues. Therefore, the compiler cannot invoke your move constructor.
In order to have your object moved, you have to write:
s.push_back(std::move(o));
// ^^^^^^^^^
What surprises me in this case is that it seems VC11 generated a copy-constructor for MyObject
implicitly without defining it as deleted (judging from the error you posted). This should not be the case, since your class declares a move constructor. Per Paragraph 12.8/7 of the C++11 Standard, in fact:
If the class definition does not explicitly declare a copy constructor, one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted (8.4)
I must conclude that while the error you are getting is correct - because you are not passing an rvalue to push_back()
- VC11 is not fully compliant here.
这篇关于使用unique_ptr移动语义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!