【问题标题】:How to intitlialize an array partially to some default value?如何将数组部分初始化为某个默认值?
【发布时间】:2020-10-26 05:29:38
【问题描述】:

我有一个数组(例如,unsigned int arr[1000])。

我想像这样初始化数组的元素..

arr = {4, 10, 34, 45, 6, 67, UINT_MAX, UINT_MAX .. 994 times}

在我分配一些值之前,我希望数组中的默认值是 UINT_MAX。

有什么办法吗?

当然 for 循环总是存在的,但除此之外还有其他方式。

【问题讨论】:

  • 你可以做memset(arr+6, -1, sizeof(unsigned int) * 1000)
  • @lucieon 这是未定义的行为。你从第 6 个元素开始写1000 更多。

标签: c++ c++11 c++14 c++20


【解决方案1】:

请使用两阶段方法。首先,使用初始化器列表,然后用std::fill 填充其余部分

#include <limits>
#include <algorithm>

constexpr size_t ArraySize = 1000U;

int main() {
    int arr[ArraySize] = { 4,10,34,45,6,67 };
    
    std::fill(arr + 6U, arr + ArraySize, std::numeric_limits<int>::max());

    return 0;
}

【讨论】:

  • 这应该被接受,因为它对 OP 的问题更清楚。
  • 由于你使用的是C++,所以不要使用C数组,首选std::array
【解决方案2】:

以下允许您使用任何类型、大小和默认值来做您想做的事情:

template<typename T, size_t Size, size_t N, size_t... In, size_t... Isize>
constexpr std::array<T, Size> make_array_impl(const T(&user_supplied)[N], T default_value, std::index_sequence<In...>, std::index_sequence<Isize...>)
{
    return {user_supplied[In]..., (Isize, default_value)...};
}

template<typename T, size_t Size, size_t N>
constexpr std::array<T, Size> make_array(const T(&user_supplied)[N], T default_value)
{
    static_assert(N <= Size, "bla bla bla");
    return make_array_impl<T, Size> (user_supplied, default_value, std::make_index_sequence<N>{}, std::make_index_sequence<Size - N>{});
}

你可以这样使用它:

int main()
{
    auto arr = make_array<unsigned int, 1000>({4, 10, 34, 45, 6, 67}, UINT_MAX); // expands to arr = {4, 10, 34, 45, 6, 67, UINT_MAX... 994 times}
}

Try it on godbolt

【讨论】:

    【解决方案3】:

    使用std::fill:

    unsigned int array[5];
    std::fill(array, array + 5, UINT_MAX);
    

    std::fill_n:

    unsigned int array[5];
    int count = 5; //           -   number of elements to modify
    auto value = UINT_MAX; //   -   the value to be assigned 
    std::fill_n(array, count, value);
    

    或者,考虑改用std::array。它是 C 样式数组的一个薄包装器,具有一些额外的功能,例如迭代器和 size() 函数。此外,它不会自动衰减为指针。

    扩展下面@Evg 的评论,更惯用、通用、安全和可靠的方法是使用库提供的功能:

    unsigned int array[5];
    // number of elements to modify
    int count = std::size(array); // C++17
    
    // the value to be assigned 
    auto value = std::numeric_limits<uint32_t>::max();
    
    std::fill_n(std::begin(array), count, value);
    
    //OR with std::fill
    std::fill(std::begin(array), std::end(array), value);
    

    上述方法的优点很明显:

    • 您可以将容器从 C 样式数组切换到 std::vectorstd::array,而无需更改上述代码中的任何其他部分。
    • 如果改变数组的大小,代码会自动适应
    • 减少人为错误的机会

    【讨论】:

    • 你可以用std::end(array)代替array + 5(和std::begin(array)对称),这样更不容易出错——没有神奇的常数5count 也一样:auto count = std::size(array);
    • 我想知道,为什么这有 4 UV 并且是公认的答案。问题是关于部分初始化,然后填充其余部分。但我们永远学不会。 . .
    猜你喜欢
    • 2017-12-08
    • 1970-01-01
    • 2011-09-03
    • 2020-06-21
    • 2017-02-21
    • 2014-05-06
    • 1970-01-01
    • 2014-11-30
    • 2015-02-25
    相关资源
    最近更新 更多