我理解你是否希望传递MyClass对象的向量并且它是一个临时变量,如果为MyClass定义了一个移动构造函数,那么这将被调用,但是如果你传递{{1}的向量会发生什么}或boost::shared_ptr<MyClass>
? shared_ptr是否有一个移动构造函数,然后调用MyClass的移动构造函数?
答案 0 :(得分:3)
是的,std::shared_ptr<T>
有一个移动构造函数,以及一个可以从相关共享指针移动的模板化构造函数,但它根本不会触及托管对象。新构造的共享指针共享托管对象的所有权(如果有的话),并且move-from指针被解除(“null”)。
示例:
struct Base {}; // N.B.: No need for a virtual destructor
struct Derived : Base {};
auto p = std::make_shared<Derived>();
std::shared_ptr<Base> q = std::move(p);
assert(!p);
答案 1 :(得分:3)
如果为MyClass定义了一个移动构造函数,那么这将被称为
通常不是。移动向量通常是我转移托管数组的所有权,将移动的向量留空。物体本身没有被触及。 (我认为如果两个向量具有不兼容的分配器可能会有异常,但这超出了我需要处理的任何内容,所以我不确定那里的细节。)
shared_ptr是否有一个移动构造函数,然后调用MyClass的移动构造函数?
没有。同样,它有一个移动构造函数,它将MyClass
对象的所有权转移到新指针,将旧指针留空。对象本身没有受到影响。
答案 2 :(得分:3)
如果您的意思是移动std::vector<std::shared_ptr<MyClass>>
。然后甚至不会调用std::shared_ptr
的移动构造函数。因为移动操作直接在std::vector
级别完成。
例如,std::vector<T>
可以实现为指向T
数组和size
成员的指针。用于此的移动构造函数可以实现为:
template <typename T>
class vector {
public:
/* ... other members */
vector(vector &&another): _p(another._p), _size(another._size) {
/* Transfer data ownership */
another._p = nullptr;
another._size = 0;
}
private:
T *_p;
size_t _size;
}
您可以在此过程中看到,根本没有触及T
类型的数据成员。
编辑:更特别是在C ++ 11标准中:§23.2.1。一般容器要求(4)有一个表包含一般容器实现的要求,其中包含以下要求:
(X
是元素的类型,u
是标识符声明,rv
是右值引用,a
是X
类型的容器)
X u(rv)
X u = rv
C ++标准:对于除std::array
之外的所有标准容器,这两个(移动构造函数)应具有恒定的时间复杂度。
因此很容易得出结论实现必须使用我上面提到的std::vector
移动构造函数的方法,因为它不能调用单个元素的移动构造函数,否则时间复杂度将变为线性时间。
a = rv
C ++标准:a
的所有现有元素要么移动分配给要么被销毁,要么等于rv
在此分配之前的值。
这是移动分配操作员。这句话只说明a
中的原始元素应该“妥善处理”(移动分配或销毁)。但这不是一个严格的要求。恕我直言的实施可以选择最合适的方式。
我还查看了Visual C ++ 2013中的代码,这是我找到的代码段(vector
标题,从第836行开始):
/* Directly move, like code above */
void _Assign_rv(_Myt&& _Right, true_type)
{ // move from _Right, stealing its contents
this->_Swap_all((_Myt&)_Right);
this->_Myfirst = _Right._Myfirst;
this->_Mylast = _Right._Mylast;
this->_Myend = _Right._Myend;
_Right._Myfirst = pointer();
_Right._Mylast = pointer();
_Right._Myend = pointer();
}
/* Both move assignment operator and move constructor will call this */
void _Assign_rv(_Myt&& _Right, false_type)
{ // move from _Right, possibly moving its contents
if (get_allocator() == _Right.get_allocator())
_Assign_rv(_STD forward<_Myt>(_Right), true_type());
else
_Construct(_STD make_move_iterator(_Right.begin()),
_STD make_move_iterator(_Right.end()));
}
在此代码中,操作很明确:如果this
和right
操作数都具有相同的分配器,它将直接窃取内容而不对单个元素执行任何操作。但如果他们没有,那么将调用单个元素的移动操作。目前,其他答案适用(适用于std::shared_ptr
个内容。)