[英]Compiler doesn't fail when pushing back a std::unique_ptr into a std::vector
An unique_ptr
cannot be pushed back into a std::vector
since it is non-copyable, unless std::move
is used. unique_ptr
不能被推回到std::vector
因为它是不可复制的,除非使用了std::move
。 However, let F
be a function that returns a unique_ptr
, then the operation std::vector::push_back(F())
is allowed. 但是,让F
是一个返回unique_ptr
的函数,然后允许操作std::vector::push_back(F())
。 There is an example below: 下面有一个例子:
#include <iostream>
#include <vector>
#include <memory>
class A {
public:
int f() { return _f + 10; }
private:
int _f = 20;
};
std::unique_ptr<A> create() { return std::unique_ptr<A>(new A); }
int main() {
std::unique_ptr<A> p1(new A());
std::vector< std::unique_ptr<A> > v;
v.push_back(p1); // (1) This fails, should use std::move
v.push_back(create()); // (2) This doesn't fail, should use std::move?
return 0;
}
(2)
is allowed, but (1)
is not. (2)
是允许的,但(1)
不是。 Is this because the returned value is moved somehow implicitly? 这是因为返回的值以某种方式隐式移动了吗?
In (2)
, is it actually necessary to use std::move
? 在(2)
,实际上是否需要使用std::move
?
std::move(X)
essentially means "here, treat X as if it was a temporary object". std::move(X)
实质上意味着“在这里,将X看作是一个临时对象”。
create()
returns a temporary std::unique_ptr<A>
to begin with, so move
is unnecessary. create()
返回一个临时的std::unique_ptr<A>
,所以不需要move
。
If you want to know more, look into the value categories . 如果您想了解更多信息,请查看值类别 。 Your compiler uses value categories to determine if an expression refers to a temporary object ("rvalue") or not ("lvalue"). 您的编译器使用值类别来确定表达式是否引用临时对象(“rvalue”)或不引用(“左值”)。
p1
is an lvalue, and create()
is an rvalue. p1
是左值, create()
是右值。
std::vector::push_back()
has an overload that takes an rvalue reference as input: std::vector::push_back()
有一个重载,它将rvalue引用作为输入:
void push_back( T&& value );
The return value of create()
is an unnamed temporary, ie an rvalue, so it can be passed as-is to push_back()
without needing to use std::move()
on it. create()
的返回值是一个未命名的临时值,即一个rvalue,因此它可以按原样传递给push_back()
而不需要在其上使用std::move()
。
std::move()
is needed only when passing a named variable, ie an lvalue, where an rvalue is expected. 只有在传递一个命名变量(即左值std::move()
时才需要std::move()
,其中rvalue是预期的。
With C++11 we got move constructors and rvalues semantics. 使用C ++ 11,我们得到了移动构造函数和rvalues语义。
std::move(X) is just a cast to a rvalue which converts X to X&& that is it. std :: move(X)只是对rvalue的强制转换,它将X转换为X &&即它。 Than move ctor takes the job over and move constructors typically "steal" the resources held by the argument. 比移动ctor接管工作并移动构造函数通常“窃取”参数所持有的资源。 unique_ptr have a move ctor. unique_ptr有一个移动ctor。
Function return values are already a rvalue(unless the function returns an lvalue reference as indicated by @HolyBlackCat in comments) which will trigger the move ctor without needing any extra cast. 函数返回值已经是一个右值(除非函数返回一个左值引用,如注释中的@HolyBlackCat所示),它将触发移动ctor而不需要任何额外的强制转换。 And since move ctor is defined for unique_ptr it will compile. 因为move ctor是为unique_ptr定义的,所以它会编译。
Also the reason why v.push_back(p1);failing is: you try to call copy constructor with an lvalue and it fails because unique_ptr does not have a copy ctor. 另外v.push_back(p1);失败的原因是:您尝试使用左值调用复制构造函数并且它失败,因为unique_ptr没有复制ctor。
It is also worth knowing that it would also work due to compiler ability to move objects that are not move explicitly (NRVO) 值得一提的是,由于编译器能够移动未明确移动的对象(NRVO),它也可以工作
#include <iostream>
#include <vector>
#include <memory>
class A {
public:
int f() { return _f + 10; }
private:
int _f = 20;
};
std::unique_ptr<A> create() {
std::unique_ptr<A> x (new A);
return x;
}
int main() {
std::unique_ptr<A> p1(new A());
std::vector< std::unique_ptr<A> > v;
//v.push_back(p1); // (1) This fails, should use std::move
v.push_back(create()); // (2) This doesn't fail, should use std::move?
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.