我认为这更像是一个哲学问题而不是技术问题:)
根本问题是移动和复制之间有什么区别。我不会跳入技术/标准语言,让我们简单地做:
- 复制:创建另一个相同的对象(或者至少,一个应该比较相等的对象)
- 移动:取出一个物体并将其放在另一个位置
如您所说,可以根据复制来实现移动:将副本创建到新位置并丢弃原始位置。然而,那里有两个问题。一是性能,二是关于用于 RAII 的对象:两者中的哪一个应该拥有所有权?
一个适当的 Move 构造函数解决了两个问题:
- 清楚的是哪个对象拥有所有权:新的,因为原来的将被丢弃
- 因此无需复制指向的资源,从而提高效率
和很好地说明了这一点auto_ptr
。unique_ptr
使用 anauto_ptr
你有一个搞砸的 Copy 语义:原始和副本不比较相等。您可以将其用于移动语义,但存在丢失指向某处的对象的风险。
另一方面,unique_ptr
就是这样:它保证了资源的唯一所有者,从而避免了复制和随之而来的不可避免的删除问题。并且在编译时也保证了无副本。因此,只要您不尝试进行复制初始化,它就适用于容器中。
typedef std::unique_ptr<int> unique_t;
typedef std::vector< unique_t > vector_t;
vector_t vec1; // fine
vector_t vec2(5, unique_t(new Foo)); // Error (Copy)
vector_t vec3(vec1.begin(), vec1.end()); // Error (Copy)
vector_t vec3(make_move_iterator(vec1.begin()), make_move_iterator(vec1.end()));
// Courtesy of sehe
std::sort(vec1.begin(), vec1.end()); // fine, because using Move Assignment Operator
std::copy(vec1.begin(), vec1.end(), std::back_inserter(vec2)); // Error (copy)
因此,您可以unique_ptr
在容器中使用(与 不同auto_ptr
),但许多操作将是不可能的,因为它们涉及类型不支持的复制。
不幸的是,Visual Studio 在执行标准方面可能相当松懈,并且还有许多扩展需要禁用以确保代码的可移植性......不要用它来检查标准:)