我在1990年开始学习我的第一个C ++课程,早在新的异常,STL和诸如此类的东西之前。现在我正在编写一个自定义C ++容器,我决定将其作为学习一些C ++ 11技术和概念的机会,尤其是unique_ptr。不幸的是,我在插入元素时遇到了移动语义(我认为)的问题。这是我试图编译的代码的一个非常简化的版本:
#include <vector>
#include <memory>
struct Key {
int k_;
Key() : k_(0){};
explicit Key(int k) : k_(k){};
Key(const Key &o) : k_(o.k_) {}
Key(Key &&o) { k_ = std::move(o.k_); }
Key &operator=(const Key &o) {
k_ = o.k_;
return *this;
}
Key &operator=(Key &&o) {
k_ = std::move(o.k_);
return *this;
}
int get() const { return k_; }
};
template <class T> class CustomContainer {
public:
typedef std::pair<Key, std::unique_ptr<Key>> Record;
CustomContainer() {}
~CustomContainer(){};
bool insert(const Record &record) {
objects.emplace_back(std::move(record));
return true;
}
std::vector<Record> objects;
};
int main() {
CustomContainer<Key> q;
q.insert(CustomContainer<Key>::Record(Key(1), std::unique_ptr<Key>(new Key(1))));
}
我正在插入一个指向Key对象的指针以保持代码简单。在我的实际应用程序中,Key有点复杂,T不是Key,而Custom容器有更多的成员函数,但这足以突出显示问题。当我在向量中只有一个unique_ptr对象时,一切看起来都很好。一旦我添加了这对,我得到:
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/ext/new_allocator.h:120:23: error: call to
implicitly-deleted copy constructor of 'std::pair<Key, std::unique_ptr<Key, std::default_delete<Key> > >'
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
.
.
.
simple.cc:33:13: note: in instantiation of function template specialization 'std::vector<std::pair<Key,
std::unique_ptr<Key, std::default_delete<Key> > >, std::allocator<std::pair<Key, std::unique_ptr<Key,
std::default_delete<Key> > > > >::emplace_back<const std::pair<Key, std::unique_ptr<Key,
std::default_delete<Key> > > >' requested here
objects.emplace_back(std::move(record));
^
simple.cc:41:5: note: in instantiation of member function 'CustomContainer<Key>::insert' requested here
q.insert(CustomContainer<Key>::Record(Key(1), std::unique_ptr<Key>(new Key(1))));
我尝试使用自定义类而不是一对同样的东西并得到相同的错误。无论我添加了多少std :: move(),我似乎无法让编译器调用移动构造函数而不是复制构造函数。我错过了什么?
答案 0 :(得分:0)
你将const ref传递给unique_ptr,然后尝试从中复制(你只能从非const移动)。传递整个对象,然后从中移动。由于您使用临时(r值引用)进行初始化,因此会在调用站点进行隐式移动。
修复代码的修补程序在这里:
template <class T> class CustomContainer {
public:
...
bool insert(Record record) { // <-- FIXED
...
}
};