如果您的意思是移动std::vector<std::shared_ptr<MyClass>>。那么即使std::shared_ptr 的移动构造函数也不会被调用。因为移动操作是直接在std::vectorlevel上进行的。
例如,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 的所有现有元素要么被移动分配,要么被销毁 a 应等于 rv 在此分配之前的值。
这是用于移动赋值运算符。这句话只说明a 中的原始元素应该“正确处理”(移动分配或销毁)。但这不是一个严格的要求。恕我直言,实现可以选择最合适的方式。
我还查看了 Visual C++ 2013 中的代码,这是我找到的 sn-p(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 的东西)。