利用初始化列表的构造函数

5

我正在使用c++实现一个容器,实际上是一个数组的包装器。我不确定如何从initializer_list中实现构造函数。我最终得到了这个实现,但它对我来说似乎非常丑陋。因此,是否可以分配在堆上并由initializer_list初始化的数组。或者有没有更优雅的方法来做到这一点?

template <typename T> class sequence {
public:
    sequence (size_t n): _data {new T[n]}, _size {n} {};
    sequence (std::initializer_list<T> source);
    ~sequence() { delete[] _data; };
private:
    pointer     _data;
    size_type   _size;
};

//Initializer list constructor
template <class T> sequence<T>::sequence (std::initializer_list<T> source)
: sequence(source.size()) {
    auto iterator = source.begin();
    for ( int i=0; i < _size; i++) {
        _data[i] = *iterator;
        ++iterator;
    }
};

[提醒] 你从未分配“_data”,而且你应该摆脱在变量名前加“_”的习惯。 - NathanOliver
你错了,我已经分配了它。我知道 _ 命名问题。实际上,我不使用那种命名风格。我只是不想重写这段代码片段。但还是谢谢你的评论。 - Jiří Lechner
好的,我打算基于序列类来实现我的向量,所以使用std::vector对我来说似乎是作弊。我主要是出于教育目的这样做,但最终可能会是个不错的选择。 - Jiří Lechner
@NathanOliver 我认为他使用了委托构造函数 - PcAF
哦,对不起。我以为它是成员变量。它是委托。 - NathanOliver
显示剩余3条评论
1个回答

6
根据你要完成的任务不同,选择的方法也不同。
如果你需要使用编译时确定大小的有界序列,则使用C++11引入的std::array<T,std::size_t>,它是一个包装器,类似于你正在实现的C风格数组。
然而,正如您在其中一条评论中所说,您主要是出于教育目的而这样做。在这种情况下,你已经做得很好了。语法可以再整理一下。考虑:
//Initializer list constructor
template <class T> 
sequence<T>::sequence (std::initializer_list<T> source)
  : sequence(source.size()) 
{
  auto it = source.begin();
  auto const e = source.cend();
  auto d = data_;
  while (it != e) {
     *d++ = *it++;
  } 
};

这样就不需要明确地依赖于 size()。你可以考虑通过将 ite 迭代器转换为“移动”迭代器来使事情更加高效:

auto it = std::make_move_iterator(source.begin());
auto e = std::make_move_iterator(source.end());

这样,每当它被解引用时,其值就会被强制转换为右值引用,从而允许进行移动赋值操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接