【问题标题】:Malloc space for a pointer of array in C++C++中数组指针的Malloc空间
【发布时间】:2021-12-25 00:57:07
【问题描述】:

我需要处理可变数量的固定大小数组。更具体地说,N 点在 K 维空间中,我事先知道 K,但在编译时我不知道 N。 所以我想使用一个指向固定大小数组的指针,并在运行时为N个K维点分配空间。

在 C 语言中,我可以使用 malloc 分配所述指针。下面的示例test.c,为简单起见,其中维度为 3:

#include <stdlib.h>
#include <stdio.h>
#define DIMENSIONS  3

typedef float PointKDimensions[DIMENSIONS];

void do_stuff( int num_points){
  PointKDimensions *points;
  points = malloc(num_points * sizeof(PointKDimensions));
  points[5][0] = 0;    // set value to 6th point, first dimension
  points[5][1] = 1.0;  // to second dimension
  points[5][2] = 3.14; // to third dimension
  return;
}

int main(){
    do_stuff(10); // at run-time I find out I have 10 points to handle
    return 0;
}

我可以用gcc test.c 编译它而不会出错,并且运行时不会出现分段错误。

但是,如果我尝试使用 C++ mv test.c test.cpp 实现相同的行为,然后是 g++ test.cpp,我会得到:

test.cpp: In function ‘void do_stuff(int)’:
test.cpp:10:18: error: invalid conversion from ‘void*’ to ‘float (*)[3]’ [-fpermissive]
10 |   points = malloc(num_points * sizeof(float) * DIMENSIONS);
   |            ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   |                  |
   |                  void*

向上搜索,发现C++并没有对malloc做隐式转换,所以我把malloc改成:

 points = (float*) malloc(num_points * sizeof(float) * DIMENSIONS);

然后错误变成:

test.cpp: In function ‘void do_stuff(int)’:
test.cpp:10:12: error: cannot convert ‘float*’ to ‘float (*)[3]’ in assignment
   10 |   points = (float*) malloc(num_points * sizeof(float) * DIMENSIONS);
      |            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |            |
      |            float*

但我找不到一种方法来进行适当的转换/转换来解决这个错误。例如,(float**) 也与 float(*)[3] 不同。

关于如何在 C++ 中为指向固定大小数组的指针分配空间有什么建议吗?

【问题讨论】:

  • 不要在 C++ 中使用 malloc。如果您想要一个运行时大小的数组,请使用std::vector

标签: c++ arrays malloc


【解决方案1】:

你可以使用std:array

例如

#include <array>

inline constexpr const size_t DIMENSIONS = 3;
using PointKDimensions = std::array<float, DIMENSIONS>;

【讨论】:

  • 虽然我在很大程度上同意这个答案,但我怀疑提问者有一些理由他们想要从免费存储而不是自动分配中获取存储。
  • 再读一遍问题,我可以看出原因是什么:num_points 不是一个固定值。答案跳过了如何正确使用malloc 和演员表,而该位的答案是“不要。使用std::vector。”
  • @user4581301 std::array 是一种聚合类型,其语义与将 C 样式数组 T[N] 作为其唯一非静态数据成员的结构具有相同的语义。 最后的问题是:关于如何在 C++ 中为指向固定大小数组的指针分配空间有什么建议吗? 我们确实有一个固定大小的数组;对于 float 类型,PointKDimensions 可以轻松复制,因此除了 malloc、memcpy 和 co。
  • @user4581301 我从 C 迁移到 C++ 学到的一件事是,指针和数组可以更好地包装到适当的类中。
  • 同意 100%。我的观点是,当他们尝试分配 num_points std::arrays 时,询问者的情况比他们尝试分配 num_points float [DIMENSIONS]s 时要好一些。 std::vector&lt;PointKDimensions&gt; points(num_points); 几乎消除了所有动态分配和强制转换问题。
【解决方案2】:

您需要将malloc 的结果转换为PointKDimensions* 而不是float*

typedef float PointKDimensions[DIMENSIONS];

void do_stuff( int num_points){
  PointKDimensions *points;
  points = (PointKDimensions*)malloc(num_points * sizeof(PointKDimensions));
  points[5][0] = 0;    // set value to 6th point, first dimension
  points[5][1] = 1.0;  // to second dimension
  points[5][2] = 3.14; // to third dimension
  return;
}

或者更好的是,使用 C++ 的内置容器来处理动态大小的数组,std::vector:

vector<vector<float>> points;

void do_stuff( int num_points){
  points.resize(num_points, vector<float>(k)); // assuming k = number of dimensions.
  points[5][0] = 0;    // set value to 6th point, first dimension
  points[5][1] = 1.0;  // to second dimension
  points[5][2] = 3.14; // to third dimension
  return;
}

【讨论】:

  • 我们知道内部数组的维数,所以在这里嵌套vectors 是不合适的。有可能大大减慢程序的速度。
  • 这正是我想要的!此外,@user4581301 提到的一点是我在保留有关已知大小的信息时试图利用的。我对 std 容器有所了解,它们更灵活、更安全,但我的目标是科学应用程序(忘了提),所以尽可能保持原始状态。还是谢谢。
  • @exepe 将此答案与 Erdal 的答案结合起来,您将获得一个非常强大且高效的解决方案。
  • @user4581301 我想写一些类似的东西。如果您希望它尽可能原始,std::vector as point 不是最佳选择,std::array 更适合。但是你一直在指出的是,而不是malloc std::vector 是合适的容器,长话短说:std::vector&lt;std::array&lt;TYPE, DIM&gt;&gt;
  • @exepe 目标是互相帮助。只要没有人给你暗示,你做错了什么,不要让那个困扰你。编码愉快。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-25
  • 1970-01-01
  • 1970-01-01
  • 2021-02-13
  • 2013-12-20
相关资源
最近更新 更多