为什么 std: : array 没有一个接受要填充的数组值的构造函数?

就是没有

std::array<T,size>::array(const T& value);

对我来说,它似乎非常有用,而动态容器(如 std::vector)确实有一个类似的构造函数。

我很清楚

std::array<T,size>::fill(const T& value);

但那不是构造函数,内存会先被清零。如果我想要所有的 -1都像 这家伙一样呢?

43969 次浏览

std::array is, by design, an aggregate, so has no user-declared constructors.

As you say, you could use fill after default constructing. Since it's an aggregate, default construction won't zero the memory, but will leave it uninitialised (if the contained type is trivially initialisable).

First of all, it is not std::array<T>, it is std::array<T,N> where N is compile time constant integral expression.

Second, std::array is made aggregate by design. So it doesn't have anything which makes it non-aggregate, which is why it doesn't have constructor... and destructor, virtual functions, etc.

Note that you can efficiently simulate this type of constructor by taking advantage of the fact that array is not zero-initialized, and has a copy constructor and do.

template <size_t N, class T>
array<T,N> make_array(const T &v) {
array<T,N> ret;
ret.fill(v);
return ret;
}


auto a = make_array<20>('z');

You may use std::index sequence for that:

namespace detail
{


template <typename T, std::size_t...Is>
constexpr std::array<T, sizeof...(Is)>
make_array(const T& value, std::index_sequence<Is...>)
{
return \{\{(static_cast<void>(Is), value)...}};
}
}


template <std::size_t N, typename T>
constexpr std::array<T, N> make_array(const T& value)
{
return detail::make_array(value, std::make_index_sequence<N>());
}

Demo

std::make_index_sequence is C++14, but can be implemented in C++11.

static_cast<void>(Is) is to handle evil operator, that T might provide.

I took answer from Jarod42 and made an extension to be able to use variable amount of Constructor arguments and also added automatic indexer as a first arg:

namespace detail {
template <typename T, std::size_t... Seq, typename... Args>
constexpr std::array<T, sizeof...(Seq)> make_array(std::index_sequence<Seq...>, Args &... args)
{
return \{\{(static_cast<void>(Seq), T(Seq, args...))...}};
}
}  // namespace detail


template <typename T, std::size_t N, typename... Args>
constexpr std::array<T, N> make_array(Args &... args)
{
return detail::make_array<T>(std::make_index_sequence<N>(), args...);
}


class myClass {
myClass(unsigned int i, float a, std::string b, int c):... {};
}


Usage:

auto myArray = make_array<myClass, 64>(a, b, c);