【问题标题】:How to initialize all elements in an array to the same number in C++如何在 C++ 中将数组中的所有元素初始化为相同的数字
【发布时间】:2010-05-23 03:32:29
【问题描述】:

我正在尝试初始化一个 int 数组,并将所有内容都设置为 -1。

我尝试了以下方法,但它不起作用。它只将第一个值设置为 -1。

int directory[100] = {-1};

为什么它不能正常工作?

【问题讨论】:

  • 在 GCC 和 clang 中,您可以作为 GNU C extension 执行 int a[100] = { [0 ... 99] = -1 };

标签: c++ arrays g++


【解决方案1】:

我对所有建议 vector 的答案感到惊讶。它们甚至不是一回事!

使用std::fill,来自<algorithm>

int directory[100];
std::fill(directory, directory + 100, -1);

不直接关心这个问题,但是当涉及到数组时,您可能需要一个不错的辅助函数:

template <typename T, size_t N>
T* end(T (&pX)[N])
{
    return pX + N;
}

给予:

int directory[100];
std::fill(directory, end(directory), -1);

所以你不需要列出两次大小。

【讨论】:

  • 我很惊讶没有人建议在初始化列表中写出 -1 100 次。
  • 请注意,std::fill_n 更简单一点:std::fill_n(directory, 100, -1);
  • @Brian R. Bondy:我很惊讶没有人建议这样做memset(directory, -1, ...)。在 2 的补码架构上,这实际上会将 int 值设置为 -1 :)
  • 在 C++11 中,std::fill(std::begin(directory), std::end(directory), -1); 有效。
  • 每个老C程序员都知道,静态分配数组的大小是sizeof(A)/sizeof(A[0])
【解决方案2】:

我建议使用std::array。三个原因:
1. 数组在下标(即operator[])操作中提供运行时安全性,防止索引越界
2.数组自动携带大小,无需单独传递
3. 最重要的是,array 提供了fill() 所需的方法 这个问题

#include <array>
#include <assert.h>

typedef std::array< int, 100 > DirectoryArray;

void test_fill( DirectoryArray const & x, int expected_value ) {
    for( size_t i = 0; i < x.size(); ++i ) {
        assert( x[ i ] == expected_value );
    }
}

int main() {
    DirectoryArray directory;
    directory.fill( -1 );
    test_fill( directory, -1 );
    return 0;
}

使用数组需要使用“-std=c++0x”进行编译(适用于上述代码)。

如果那不可用或者如果那不是一个选项,则可以选择其他选项,例如 std::fill()(如 GMan 所建议的)或手动编码 a fill() 方法。

【讨论】:

  • 对我来说最重要的是它内部的原生数组。如果数组实例在堆栈上,则全部在堆栈上分配。当然,如果没有 C++0x 支持,boost::array 或者自己封装的 C 数组也可以。
  • @Johannes:是的, 内部包含一个原生数组,这很重要。我错过了提到这一点。谢谢!
  • #1 是错误的:operator[] 不执行边界检查,仅执行 .at() 方法(除非您使用某些带有调试选项的 stdlib impls 也在 operator[] 上执行此操作,但这绝对不是标准行为)。 #2 并不特定于std::array:数组可以通过引用传递,所以一个简单的模板函数可以确定大小,在 C++17 中,我们有 std::size() 的重载。并且#3 是不合理的:我们也可以std::fill() 一个普通数组,使用指向它的第一个和过去一个元素的指针,从 C++11 开始可以使用 std::begin()std::end() 获得。
【解决方案3】:

如果您的元素数量较少,您可以一个接一个地指定它们。数组初始化通过指定每个元素来工作,而不是通过指定适用于每个元素的单个值。

int x[3] = {-1, -1, -1 };

您还可以使用向量并使用构造函数来初始化所有值。稍后您可以通过指定 &amp;v.front()

来访问原始数组缓冲区
std::vector directory(100, -1);

还有一种 C 方法也可以使用 memset 或各种其他类似函数。 memset 适用于您指定缓冲区中的每个字符,因此它适用于 0 之类的值,但可能无法正常工作,具体取决于为 -1 存储负数的方式。


您还可以使用 STL 通过 fill_n 来初始化您的数组。对于每个元素的通用操作,您可以使用 for_each。

fill_n(directory, 100, -1);

或者如果你真的想要你可以走跛脚的方式,你可以做一个 100 次迭代的 for 循环并做 directory[i] = -1;

【讨论】:

    【解决方案4】:

    如果你真的需要数组,你可以使用 boosts array 类。它的分配成员完成了这项工作:

    boost::array<int,N> array; // boost arrays are of fixed size!
    array.assign(-1);
    

    【讨论】:

      【解决方案5】:

      它确实工作正常。您对初始化程序的期望是不正确的。如果您真的希望采用这种方法,您将需要在初始化程序中使用 100 个逗号分隔的 -1。但是当你增加数组的大小时会发生什么?

      【讨论】:

      • 我们把所有这些开发人员带到了后面,不久前就开枪了!
      【解决方案6】:

      使用 int 向量代替数组。

      vector<int> directory(100,-1);                       // 100 ints with value 1
      

      【讨论】:

        【解决方案7】:

        它工作正常。这就是列表初始值设定项的工作方式。

        我相信 C99 标准的 6.7.8.10 涵盖了这一点:

        如果一个对象具有自动 存储持续时间未初始化 明确地,它的值是 不定。如果一个对象有 静态存储时间不 显式初始化,然后:

        • 如果有指针类型,则初始化为空指针;
        • 如果它有算术类型,则初始化为(正数或无符号数) 零;
        • 如果它是一个聚合,每个成员都被初始化(递归)根据 遵守这些规则;
        • 如果是联合,则初始化第一个命名成员(递归) 根据这些规则。

        如果您需要使数组中的所有元素都具有相同的非零值,则必须使用循环或memset

        还要注意,除非你真的知道自己在做什么,否则vectors are preferred over arrays in C++

        关于容器与数组,您需要了解以下几点:

        1. 容器类使程序员的工作效率更高。因此,如果你坚持使用数组,而周围的人都愿意使用容器类,那么你的工作效率可能会比他们低(即使你比他们更聪明、更有经验!)。
        2. 容器类让程序员编写更健壮的代码。所以如果你坚持使用数组,而周围的人愿意使用容器类,你的代码可能会比他们的代码有更多的错误(即使你更聪明、更有经验)。
        3. 如果您非常聪明且经验丰富,可以像使用容器类一样快速和安全地使用数组,那么其他人可能最终会维护您的代码,并且他们可能会引入错误。或者更糟的是,您将是唯一可以维护您的代码的人,因此管理层会将您从开发中拉出来并让您担任全职维护角色——这正是您一直想要的!

        链接的问题还有很多;读一读。

        【讨论】:

        • vector 不是数组的首选。他们是两个不同的东西。在我目前的情况下,哪个是最好的就是首选。
        【解决方案8】:

        你只需使用 for 循环,如下所示:-

        for (int i=0; i<100; i++)
        { 
        a[i]= -1;
        }
        

        因此你可以得到 A[100]={-1,-1,-1.......(100次)}

        【讨论】:

          【解决方案9】:

          我有同样的问题,我找到了怎么做,文档给出了以下示例:

          std::array<int, 3> a1{ {1, 2, 3} }; // double-braces required in C++11 (not in C++14)
          

          所以我只是尝试了:

          std::array<int, 3> a1{ {1} }; // double-braces required in C++11 (not in C++14)
          

          它的工作原理是所有元素都以 1 为值。它不适用于 = 运算符。可能是 C++11 问题。

          【讨论】:

          • 赞成将所有元素初始化为一个给定值。现在,.忽略 "std::vector" 和 "std::array" ,你可以说:int directory[100]{-1};
          • 这是错误的:给定的语法将第一个元素初始化为 1,其余元素初始化为 0。
          【解决方案10】:

          无法使用原始数组执行您想要执行的操作(除非您在初始化列表中明确列出所有 100 个 -1s),您可以使用 vector 来执行此操作:

          vector<int> directory(100, -1);
          

          此外,您可以使用提到的其他方法之一创建数组并将值设置为-1

          【讨论】:

          • @Brian R. Bondy:是的,当然,但这只是迂腐。 memset,fill,for-loop 是很好的解决方案,但它们不是在初始化时设置的。对于原始数组,它是 {-1,-1,...x100} 或在之后设置它们。
          • 是的,我想在声明时你有一个。
          【解决方案11】:

          只需使用这个循环。

          for(int i =0 ; i < 100 ; i++) directory[i] =0;
          

          【讨论】:

            【解决方案12】:

            全能的 memset() 将为 C/C++/C++11/C++14 中的数组和标准容器完成这项工作

            【讨论】:

            • 我喜欢 - 老派!
            【解决方案13】:

            int directory[100] = {-1} 不起作用的原因是 array initialization 发生的事情。

            所有未显式初始化的数组元素都以与具有静态存储持续时间的对象相同的方式隐式初始化。

            ints 是 implicitly initialized 是:

            初始化为无符号零

            所有未显式初始化的数组元素都以与具有静态存储持续时间的对象相同的方式隐式初始化。

            C++11 引入了beginend,它们专门用于数组!

            这意味着给定一个数组(不仅仅是一个指针),比如你的directory,你可以使用fill,正如几个答案中所建议的那样:

            fill(begin(directory), end(directory), -1)
            

            假设您编写了这样的代码,但在忘记如何实现该功能后决定重用该功能,但您决定将 directory 的大小更改为 60。如果您使用 @987654334 编写代码@ 和 end 然后你就完成了。
            另一方面,如果您这样做了:fill(directory, directory + 100, -1),那么您最好记住将 100 也更改为 60,否则您将获得未定义的行为。

            【讨论】:

              【解决方案14】:

              如果允许你使用 std::array,你可以执行以下操作:

              #include <iostream>
              #include <algorithm>
              #include <array>
              using namespace std;
              
              template <class Elem, Elem pattern, size_t S, size_t L>
              struct S_internal {
                  template <Elem... values>
                  static array<Elem, S> init_array() {
                      return S_internal<Elem, pattern, S, L - 1>::init_array<values..., pattern>();
                  }
              };
              
              template <class Elem, Elem pattern, size_t S>
              struct S_internal<Elem, pattern, S, 0> {
                  template <Elem... values>
                  static array<Elem, S> init_array() {
                      static_assert(S == sizeof...(values), "");
                      return array<Elem, S> {{values...}};
                  }
              };
              
              template <class Elem, Elem pattern, size_t S>
              struct init_array
              {
                  static array<Elem, S> get() {
                      return S_internal<Elem, pattern, S, S>::init_array<>();
                  }
              };
              
              void main()
              {
                  array<int, 5> ss = init_array<int, 77, 5>::get();
                  copy(cbegin(ss), cend(ss), ostream_iterator<int>(cout, " "));
              }
              

              输出是:

              77 77 77 77 77

              【讨论】:

                【解决方案15】:

                只需使用fill_n() 方法。

                示例

                int n;
                cin>>n;
                int arr[n];
                int value = 9;
                fill_n(arr, n, value); // 9 9 9 9 9...
                

                Learn More 关于fill_n()

                您可以使用fill() 方法。

                示例

                int n;
                cin>>n;
                int arr[n];
                int value = 9;
                fill(arr, arr+n, value); // 9 9 9 9 9...
                

                Learn More 关于fill() 方法。

                注意:algorithm 库 (#include&lt;algorithm&gt;) 中提供了这两种方法。不要忘记包含它。

                【讨论】:

                  【解决方案16】:

                  从 C++11 开始,您还可以使用基于范围的循环:

                  int directory[10];
                  for (auto& value: directory) value = -1;
                  

                  【讨论】:

                    猜你喜欢
                    • 2018-03-17
                    • 1970-01-01
                    • 2015-11-11
                    • 2016-12-09
                    • 1970-01-01
                    • 2014-07-23
                    • 1970-01-01
                    • 2010-09-17
                    • 2012-04-22
                    相关资源
                    最近更新 更多