简体   繁体   English

在类构造函数中设置std :: vector,使用元素构造函数的不同值

[英]Setup std::vector in class constructor with different values for element constructor

I have a class with a non trivial constructor: 我有一个非常简单的构造函数的类:

class mystream
{
public:
    mystream(size_t buffersize,size_t index) : buffersize(buffersize),index(index){}

    size_t buffersize;
    size_t index;
};

The mystream instance has an unique id which corresponds with its position in a vector of the managing class: mystream实例有一个唯一的id,它对应于它在管理类的向量中的位置:

class mystreammanager
{
public:
   mystreammanager() : streams(8,1024, /* WHAT TO DO HERE ??? */ )
   {
   }

  std::vector<mystream> streams;
};

How can I construct the vector and initialize its elements with an ascending value for the index? 如何构造向量并使用索引的升序值初始化其元素?

A succinct, clear and easy-to-debug way to do this is to defer the construction of the vector to a static class function: 一个简洁,清晰且易于调试的方法是将向量的构造推迟到静态类函数:

class mystreammanager
{
public:
   mystreammanager() : streams{ generate_streams(1024, 8) }
   {
   }

private:
  static std::vector<mystream> generate_streams(size_t buffersize, size_t qty)
  {
    std::vector<mystream> result;
    result.reserve(qty);
    for(size_t i = 0 ; i < qty ; ++qty) {
      result.emplace_back(buffersize, i); 
    }
    return result;
  } 

  std::vector<mystream> streams;
};

This is optimally efficient because: 这是最佳效率,因为:

  1. RVO causes the vector to be constructed in-place RVO使得载体就地构建
  2. avoiding list-initialisation means no redundant copies. 避免列表初始化意味着没有冗余副本。

Just use a loop: 只需使用一个循环:

mystreammanager() {
    streams.reserve(8);
    for (int i = 0; i < 8; ++i) {
        streams.emplace_back(1024, i);
    }
}

Compile time version :) 编译时间版:)

Requires c++14 but could surely be adapted for c++11 需要c++14但肯定可以适应c++11

#include <cstddef>
#include <vector>
#include <utility>

class mystream
{
public:
  mystream(size_t buffersize,size_t index) : buffersize(buffersize),index(index){}

  size_t buffersize;
  size_t index;
};

template<size_t... Indexes>
std::initializer_list<mystream>    mystream_maker_impl(std::index_sequence<Indexes...>)
{
  return {{1024, Indexes}...};
}

template<size_t N>
std::initializer_list<mystream>    mystream_maker()
{
  return mystream_maker_impl(std::make_index_sequence<N>());
}

class mystreammanager
{
public:
  mystreammanager() : streams(mystream_maker<8>())
  {
  }

  std::vector<mystream> streams;
};

You can do: 你可以做:

class mystreammanager
{
public:
   mystreammanager() : streams{{1024, 0}, {1024, 1}, {1024, 2}, {1024, 3},
                               {1024, 4}, {1024, 5}, {1024, 6}, {1024, 7}}
   {
   }

  std::vector<mystream> streams;
};

But doing a loop seems safer/simpler. 但做一个循环似乎更安全/更简单。

I used the answer from @RichardHodges as I was not happy with my first choice. 我使用了@RichardHodges的答案,因为我对我的第一选择不满意。 I came up with this template: 我想出了这个模板:

template<class T,class ...Args> std::vector<T> generate_with_index(size_t qty,Args ...args)
{
    std::vector<T> result;
    result.reserve(qty);
    for(size_t i = 0 ; i < qty ; ++qty)
        result.emplace_back(i, args...);
    return result;
}

It helps me avoiding redundancy. 它可以帮助我避免冗余。 From a theoretical view I like @Drax solution most as it do the most work during compile time. 从理论上来看,我最喜欢@Drax解决方案,因为它在编译期间做了大部分工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM