【问题标题】:Initialization of array on heap堆上数组的初始化
【发布时间】:2011-06-02 01:14:58
【问题描述】:

如何在堆上手动初始化数组中的值? 如果数组是局部变量(在堆栈中),则可以非常优雅且简单地完成,如下所示:

int myArray[3] = {1,2,3};

不幸的是,下面的代码

int * myArray = new int[3];
myArray = {1,2,3};

编译输出错误

error: expected primary-expression before ‘{’ token
error: expected `;' before ‘{’ token

我必须使用循环,还是像这样不太优雅的方式?

myArray[0] = 1;
myArray[1] = 2;
myArray[2] = 3;

【问题讨论】:

  • 从您的示例的外观来看,您希望使用值 1 .. N + 1 填充数组元素 0 .. N。for 循环可以很好地做到这一点。你的实际意图是什么?

标签: c++ memory-management heap-memory stack-memory


【解决方案1】:

今天可以使用以下语法来完成:

int * myHeapArray = new int [3] {1, 2, 3};

请注意,您必须将分配的结构的大小与初始化列表的大小相匹配。

由于我在回答几年前发布的问题,因此值得一提的是,现代 C++ 不鼓励使用 newdelete 和本机(或裸)指针。更喜欢使用诸如std::unique_ptrstd::shared_ptr 之类的处理程序,因为它们会自动释放它们拥有的内存(检查RAII idiom)。

在这种特殊情况下,std::vector 将提供所有此类功能:堆分配数据、使用初始化列表(如 {1, 2, 3})、处理程序和移动语义等功能。

对于堆栈分配的数组,如果需要,可以考虑std::array

【讨论】:

  • 很好的答案,谢谢。
【解决方案2】:

这很有趣:Pushing an array into a vector

但是,如果这对您不起作用,请尝试以下操作:

#include <algorithm>
...


const int length = 32;

int stack_array[length] = { 0 ,32, 54, ... }
int* array = new int[length];

std::copy(stack_array, stack_array + length, &array[0]);

【讨论】:

  • 你打错了,应该是std::copy(stack_array, stack_array+5, &amp;array[0]);
  • VLA(可变长度数组)不是 C++ 标准的一部分
  • C++ 中的 VLA 所以 -1
【解决方案3】:

您可以定义常量数组,例如 myConstArray[] = {1, 2, 3} 并在 new int[3] 之后执行 memcpy。

【讨论】:

  • 更一般地说,使用 std::copy 复制对象而不是位模式。
  • 不幸的是,这充其量是低效的,最坏的情况是不可能的(如果类型是没有复制/赋值的类)。
  • 类型是一个没有复制/赋值的类,根本不可能使用常量数组。
【解决方案4】:

{1,2,3} 是一种非常有限的语法,特定于 POD 结构初始化(显然 C 样式数组也被认为是一种)。你唯一能做的就是int x[] = {1,2,3};int x[3] = {1,2,3};,但你不能既不做int x[3]; x={1,2,3};也不能在任何其他地方使用{1,2,3}

如果您正在使用 C++,最好使用 std::vector 之类的东西而不是 C 样式的数组,因为它们被认为是危险的 - 例如,您无法知道它们的大小并且必须使用 @987654326 删除它们@,不是普通的delete。但是,使用 std::vector 您仍然会遇到相同的初始化问题。如果我经常使用这种初始化,我很可能会创建一个分配给虚拟局部变量的宏,然后将内存复制到目标。

编辑:你也可以这样做(std::vector 仍然更可取):

int* NewArray(int v1, int v2, int v3) { /* allocate and initialize */ }
int* p = NewArray(1,2,3);

但是你必须用不同数量的参数覆盖函数,或者使用 va_arg ,这又是不安全的。

EDIT2:我的回答只对 C++03 有效,因为其他人提到 C++0x 对此有一些改进。

【讨论】:

    【解决方案5】:

    C++0x 标准具有称为initializer_list 的特殊类型及其特殊语法(表达式{1, 2, 3} 的类型为std::initializer_list&lt;int&gt;)。 std::vectorstd::array 有它的构造函数,所以你可以写 vector&lt;int&gt; v = {1, 2, 3}

    C++98/C++03没有好的解决办法。

    【讨论】:

      【解决方案6】:

      如果您想要一个适用于所有类型的通用答案,那么您要做的是:

      1. malloc() 或 operator new() 创建一个长度正确的未初始化存储数组,由 nelts * sizeof(T) 计算

      2. 为每个元素创建一个包含构造函数参数的数组。

      3. 使用相应的参数以放置形式将构造函数应用于每个元素。

      这只有在每个元素都使用相同的构造函数时才有效。如果没有,您将需要更复杂的数据结构和算法来为每个元素选择正确的构造函数。

      这种情况的一个特殊情况是使用实际元素的数组并使用复制构造函数,一种特殊情况是当类型是 POD 时,您可以使用 memcpy 一次构造该批次。

      如果构造函数有两个参数,您将需要编写一个启动程序(包装器)。例如:

      pair<double> init_data[] = {make_pair(1.0,0.0), make_pair(3.0,4.0)};
      void init(void *p, pair<double> d) { new (p) complex(d.first, d.second); }
      

      并使用它而不是仅仅使用 new(p)。

      【讨论】:

        【解决方案7】:

        你也可以这样初始化:

        int * myArray = new int[3];
        *myarray=1;
        *(myarray+1)=2;
        *(myarray+2)=3;
        

        【讨论】:

          猜你喜欢
          • 2015-01-05
          • 1970-01-01
          • 2016-01-18
          • 2022-10-14
          • 1970-01-01
          • 2023-04-09
          • 2018-04-11
          • 1970-01-01
          • 2011-03-29
          相关资源
          最近更新 更多