将unique_ptr的向量传递给对象。向量成为成员变量。正确的做法?

时间:2014-11-07 12:04:22

标签: c++ oop c++11

我将调用的一个对象"所有者",在其生命周期内拥有数据对象向量的明确所有权。

这些存储为unique_ptr的载体。

一个名为"输出"的对象/类需要以许多不同的方法查看这些数据对象,因此某种的引用/指针/变量是成员变量"输出"。

Output在其构造函数中接收数据对象的向量。

我想到了实现这一目标的三种方法。什么被认为是最好的方式?

选项1 - "输出" object将数据vec存储为const引用:

class Output {
    // output wants the data:
 public:
    Output(std::vector<std::unique_ptr<Data>> const & in)
        : my_lot_of_data(in) {
    };
    std::vector<std::unique_ptr<Data>> const & my_lot_of_data;
}

由&#34;所有者&#34;实例化。用:

 data_vec_.push_back(std::unique_ptr<Data>(new Data));
 /* stuff happens to data */
 Output output(data_vec_);

选项2 - &#34;输出&#34; object将数据vec存储为const指针:

class Output {
    // output wants the data:
 public:
    Output(std::vector<std::unique_ptr<Data>> const * in)
        : my_lot_of_data(in) {
    };
    std::vector<std::unique_ptr<Data>> const * my_lot_of_data;
}

由&#34;所有者&#34;实例化。用:

 data_vec_.push_back(std::unique_ptr<Data>(new Data));
 /* stuff happens to data */
 Output output(&data_vec_);

选项3 - &#34;输出&#34; object接收原始指针:

class Output {
    // output wants the data:
 public:
    Output(std::vector<Data*> in)
        : my_lot_of_data(in) {
    };
    std::vector<Data*> const my_lot_of_data;
};

由&#34;所有者&#34;实例化。用:

 data_vec_.push_back(std::unique_ptr<Data>(new Data));
 /* stuff happens to data */
 std::vector<Data*> data_as_raw;
 data_as_raw.resize(data_vec_.size());
 std::transform(data_vec_.begin(), data_vec_.end(), data_as_raw.begin(), [](std::unique_ptr<Data> const & x) {return x.get();});
 Output output(data_as_raw);

其他查询: 在选项1和2中,很明显输出没有数据的所有权,即使它存储为unique_ptrs? 选项3是否在通话网站凌乱?需要3行才能达到相同的效果。

这里的最佳做法是什么?

4 个答案:

答案 0 :(得分:3)

如果你需要的只是“读取一些值,然后[创建]各种输出文件”我会把它变成一个const-ref所需的函数:

void output(std::vector<std::unique_ptr<Data>> const& data) {
    // stuff
}

我更喜欢const&const*的使用语义(data[0] vs (*data)[0]),并且绝对更喜欢传递原始数据 - 不要放弃你的没有任何明确的所有权(在这种情况下,考虑到构建vector<Data*>非常烦人,它甚至不方便)

答案 1 :(得分:2)

由于您使用的是unique_ptr,因此您不打算与可能持续时间超过Owner的任何内容共享此数据,因此简单的const引用应该是好的。我会推荐一个很好的typedef:

typedef std::vector<std::unique_ptr<Data>> OwnerDataSet;
Output(const OwnerDataSet &in)

方法1的优点是简单明了。其他人只是因为没有明显的原因而使其复杂化。

unique_ptr的功能是在std :: vector被破坏时删除新数据。这里的替代方法是复制Data实例而不是调用new。如果您不需要使用指针,那么您不需要像unique_ptr这样的特殊处理来保证它们的安全。

typedef std::vector<Data> OwnerDataSet;
OwnerDataSet results;
Data match = findoneresult();
results.push_back(match); // copy something from Owner
Output (results);

为了更进一步,从您的示例中不清楚为什么要在Output类之外维护std :: vector。由于您在传递的所有内容上调用std :: unique_ptr(new T),我怀疑您只将它与Output一起使用,因此您可以这样做:

class Output : public std::vector<Data> {
    void PrintToScreen();
    void WriteToDatabase();
    void OrWhatever();
};

Output x;
Data match = findoneresult();
x.push_back(findoneresult());
x.PrintToScreen();

答案 2 :(得分:0)

我会混合前两种方法:让Output构造函数通过const-ref获取向量,但将其存储为const指针。这是因为可以复制const指针,以便在需要时可以分配整个Output对象。

答案 3 :(得分:0)

如果可能的话,我会避免传递向量,并将unique_ptr的向量封装在Owner内。 Output是否有指向Owner的指针/引用并获取Data中各个Owner元素的原始指针?

class Owner {
  private:
    std::vector<std::unique_ptr<Data>> data_vec_;
  public:
    const Data* getData(size_t i) const { return data_vec_.at(i).get(); }
    size_t getSize() const { return data_vec_.size(); }
};

class Output {
  private:
    const Owner& owner_;   
  public:
    Output(const Owner& owner) : owner_(owner) { }
    void doSomething() { 
         // get some data
         auto data = owner_.getData(0);

         // use data...
    }
};