首页 > 解决方案 > 为什么初始化列表只能用于声明?

问题描述

可以使用所谓的初始化列表来初始化数组。

例如:

int my_array[3] = {10, 20, 30};

当我们的数组有一组初始值时,这非常有用。但是,一旦声明了数组,这种方法就无法为数组分配新值。

my_array = {10, 20, 30};

error: assigning to an array from an initializer list

然而,有时我们需要多次将数组初始化为一些初始值(例如:在循环中),所以我认为能够使用初始化列表将值分配给已经声明的变量会非常有用。

我的问题是:是否有理由在声明时拥有这样的功能,但在声明数组后却没有?为什么它在一种情况下有效,而在另一种情况下无效?

标签: c++arraysinitializer-list

解决方案


数组是 C++ 中的二等公民。它们对象,但受到严格限制:它们不能被复制,它们在各种上下文中衰减为指针等。考虑使用std::array,它是内置数组顶部的(固定大小)包装器,但它是第一个- 支持各种便利功能的类公民:

std::array<int, 3> my_array = {10, 20, 30};
my_array = {40, 50, 60};

这是有效的,因为根据[array.overview]/2

std::array是一种聚合类型,最多可以使用N其类型可转换为的元素进行列表初始化T

live demo

这也适用于std::vector. 向量是一个不同的故事,所以我不打算在这里详细介绍。


如果您更喜欢坚持使用内置数组,这是我设计的一种解决方法,用于使用模板元编程技术将值列表分配给内置数组(尊重值类别)。如果数组的长度和值列表不匹配,则会(正确地)引发编译时错误。(感谢Caleth的评论指出这一点!)请注意,在 C++ 中复制内置数组是不可能的;这就是为什么我们必须将数组传递给函数。

namespace detail {
  template <typename T, std::size_t N, std::size_t... Ints, typename... Args>
  void assign_helper(T (&arr)[N], std::index_sequence<Ints...>, Args&&... args)
  {
    ((arr[Ints] = args), ...);
  }
}

template <typename T, std::size_t N, typename... Args>
void assign(T (&arr)[N], Args&&... args)
{
  return detail::assign_helper(arr, std::make_index_sequence<N>{}, std::forward<Args>(args)...);
}

并使用它:

int arr[3] = {10, 20, 30};
assign(arr, 40, 50, 60);

现在arr40, 50, 60.

live demo


推荐阅读