【问题标题】:Wrapping a unique_ptr with custom class in a container在容器中包装带有自定义类的 unique_ptr
【发布时间】:2015-10-11 16:17:03
【问题描述】:

我在 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(),我似乎都无法让编译器调用移动构造函数而不是复制构造函数。我错过了什么?

【问题讨论】:

  • 你不能从const的东西上移开。
  • 我现在感觉很蠢。是的,就是这样。谢谢,克雷克。如果您想将其添加为正式答案,我很乐意接受。

标签: c++ c++11 move unique-ptr


【解决方案1】:

您将 const ref 传递给 unique_ptr,然后尝试从中复制(您只能从非常量移动)。通过整个对象,然后从中移动。由于您使用临时(r 值引用)进行初始化,因此调用站点将有一个隐式移动。

修复代码的补丁在这里:

template <class T> class CustomContainer {
public:
   ...
    bool insert(Record record) { // <-- FIXED
       ...
    }
};

【讨论】:

  • 谢谢,理查德。就是这样。原来这实际上是this one 的副本。现在我看到了答案是显而易见的。
  • 显然我不需要告诉你,一个key与value相同的map就相当于一个set……对吧?
  • 是的,就像我说的那样,我试图将所有内容简化到不会太难看的地方。
  • :) unique_ptr&lt;int&gt; 很难看...(我知道,我知道,这是对真实事物的不幸替代)。但它会标记一些你应该检查的东西,如果你有一段时间没有使用 c++。有空的时候看看 boost::optional 的 boost 库。
猜你喜欢
  • 2012-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-16
  • 1970-01-01
  • 1970-01-01
  • 2016-11-23
  • 1970-01-01
相关资源
最近更新 更多