【问题标题】:Keeping a vector of non-constructible objects保留不可构造对象的向量
【发布时间】:2013-03-21 07:27:41
【问题描述】:

我有课程MyObject。它的所有实例都应由MyObjectSet 拥有,并且不应在其他任何地方构造它。在MyObjectSet 内部,我使用std::vector<MyObject> 来存储所有实例。

问题是,要使std::vector<MyObject> 工作,MyObject 的移动构造函数必须是公开的(仅将std::vector<MyObject> 添加为MyObject 的朋友是不够的)。

class MyObject {
    MyObject(int n);
    friend class MyObjectSet;
  public:
    MyObject(MyObject&&) = default; // without this, it doesn't compile
};

class MyObjectSet {
    std::vector<MyObject> MyObjects;
  public:
    MyObject& GetMyObject(int some_param);
};

但如果我将其公开,则可以从其他地方实例化MyObject

void SomeUnrelatedFunc(MyObjectSet& set) {
    MyObject m(std::move(set.GetMyObject(0))); // this shouldn't be possible
}

有没有办法解决这个问题?

可以将指向MyObject 实例的指针存储在MyObjectSet 中,但如果可能的话,我想避免这种情况。

【问题讨论】:

  • 您是否也反对将智能指针存储到MyObject? (如果是,为什么?)
  • 你可以将 GetMyObject 的 retval 设为 const 引用吗?
  • 我没有看到允许移动构造函数的问题。它不允许您创建新对象,除非您使现有对象无效,因此您只是将资源从一个实例移动到另一个实例。而且,如果您同时禁止复制和移动,那么您的课程将很难用于任何事情

标签: c++ c++11


【解决方案1】:

你需要声明std::allocator&lt;MyObject&gt;为好友:

class MyObject {

    MyObject(int n);
    friend class MyObjectSet;
    friend std::allocator<MyObject>;
};

然后使用vector::emplace_back() 实际构造您的对象。

class MyObjectSet {
    std::vector<MyObject> MyObjects;

public:
    MyObject& GetMyObject(int some_param)
    {
        MyObjects.emplace_back( some_param );
        return MyObjects.back();
    }
};

emplace_back()的作用是调用MyObject构造函数,将some_param作为int参数传递给构造函数,将创建的对象插入到列表的后面。构造调用是从 std::allocator 内部完成的,因此需要它的友谊。

【讨论】:

  • 不幸的是,也不起作用。它抱怨移动构造函数在实例化几个实现细节模板中是私有的。我不能让他们都成为朋友类。
  • @Zyx2000 Hm.. 适用于 Clang 和 libc++。我不认为 GCC 在这方面会有所不同。
  • 啊,我明白了。 GNU 使用__gnu_cxx::new_allocator 作为分配器的名称。好吧,另一个答案即将到来......
【解决方案2】:

您可以创建一个自定义分配器并将其作为第二个参数传递给您的std::vector&lt;&gt;。让您的自定义分配器成为 MyObject 的朋友。您的自定义分配器不需要做任何特殊的事情——唯一的目的是在访问私有构造函数时以通常的方式(例如使用 new)分配 MyObjects。

【讨论】:

    猜你喜欢
    • 2016-06-13
    • 1970-01-01
    • 1970-01-01
    • 2011-11-06
    • 1970-01-01
    • 2016-02-05
    • 2018-01-11
    • 2015-05-06
    • 1970-01-01
    相关资源
    最近更新 更多