【问题标题】:Emplace back fails at in place constructionEmplace back 在原地施工中失败
【发布时间】:2017-07-13 11:28:39
【问题描述】:

我有一个对象,我想只构造一次,因为它所在的类通过向它们添加原始指针来跟踪它的对象。不过,内联构造它似乎失败了:

// Defined utilities:
ModuleClusterPlot(Type typeArg, const int& layer, const int& module, const int& ladder, const int& startEventArg, const int& endEventArg);
~ModuleClusterPlot();
// Invalid utilities
ModuleClusterPlot(ModuleClusterPlot& t_other) = delete;
ModuleClusterPlot(ModuleClusterPlot&& t_other) = delete;
ModuleClusterPlot& operator=(const ModuleClusterPlot& t_other) = delete;
ModuleClusterPlot& operator=(ModuleClusterPlot&& t_other) = delete;

通过 emplace back 调用构造函数失败,因为它试图调用移动构造函数(为什么?):

moduleClusterPlots.emplace_back(t_type, t_layer, t_module, t_ladder, i, i);

我在这里做错了什么?我正在使用gcc 7.1.0std=c++14 标志。

小例子:

#include <vector>

class ModuleClusterPlot
{
    public:
        enum Type
        {
            foo = 0,
            bar
        };

        ModuleClusterPlot(Type typeArg);
        ~ModuleClusterPlot();
        // Invalid utilities
        ModuleClusterPlot(ModuleClusterPlot& t_other) = delete;
        ModuleClusterPlot(ModuleClusterPlot&& t_other) = delete;
        ModuleClusterPlot& operator=(const ModuleClusterPlot& t_other) = delete;
        ModuleClusterPlot& operator=(ModuleClusterPlot&& t_other) = delete;

};

int main()
{
    std::vector<ModuleClusterPlot> collection;
    collection.emplace_back(ModuleClusterPlot::foo);
}

如何防止在此处调用移动构造函数?

【问题讨论】:

  • 你能把这个设为minimal reproducible example吗?
  • 你写你想添加raw pointers但是如果你得到一个需要复制/移动构造函数的错误消息,我猜你是在尝试插入一个对象而不是指针!跨度>
  • @ThomasSparber 我将this 添加到保存指针的静态对象中。
  • @AdamHunyadi 好的,请按照 NathanOliver 的建议显示代码并发布 MCVE
  • @ThomasSparber 我会这样做,不过我的问题更笼统,我想阻止 emplace back 调用移动构造函数。

标签: c++ constructor c++14 move-constructor in-place


【解决方案1】:

std::vector&lt;T&gt;::emplace_back 需要移动构造函数或复制构造函数。原因是它可能需要重新分配内存并将现有对象移动/复制到新缓冲区中。

即使您只在空向量上调用它,实际上不需要移动任何现有对象,请记住,相同的函数 emplace_back 可以用于空向量和非空向量。函数不可能知道它只在空状态下被使用,所以当成员函数被实例化时,处理非空向量的代码也必须有效。

【讨论】:

  • 那我把我的容器改成链表,谢谢你真正解释为什么它需要移动构造!
【解决方案2】:

您违反了emaplce_back 的约束。如果我们从 [sequence.reqmts] 中查看表 101,我们有

要求:T 应可从 args 中 EmplaceConstructible 到 X。 对于向量,T 也应该是 MoveInsertable 到 X 中的。

强调我的

由于您的课程不可移动插入,因此不适用于emplace_back

之所以需要这样做是因为size() 变得大于capacity(),然后向量需要分配新的存储空间并将元素移动到新的存储空间。如果它不能做到这一点,那么向量就不能按预期工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-07
    • 1970-01-01
    • 2019-02-05
    • 2021-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多