【问题标题】:Casting memory allocation return value to array of TYPE将内存分配返回值转换为 TYPE 数组
【发布时间】:2020-01-15 10:36:03
【问题描述】:

尝试在 VisualStudio 中执行以下操作,但没有成功。 基本上我输入了TypeA,我想创建一个TypeA的数组,比如说TypeA array[10];

但我希望数组在堆上而不是在堆栈上,因为它会很大(比如0x200000)或其他东西。

所以,我试图在代码方面做的事情如下:

struct TypeA {
    UINT64 a;
    UINT64 b;
    UINT64 c;
    UINT64 d;
};

TypeA array[0x10000] = (TypeA[0x10000])malloc(sizeof(TypeA)*0x10000);

【问题讨论】:

  • 为什么不使用std::vector?在没有placement-new 的情况下在这里使用malloc 在技术上是未定义的行为,如果TypeA 碰巧变得不平凡,迟早会给你带来麻烦。
  • 具有超过 200 万个元素的单个数组消耗超过 66 MB 的内存(如您所指定的)通常表示设计选择不佳。您需要考虑使用模式(例如,这 200 万个元素中有多少通常真正需要一次在内存中)。无论如何,在 C++ 中真正需要这样一个数组的极少数实际情况下,使用标准容器(如std::vector<TypeA>)而不是显式管理动态内存。并改掉以十六进制指定数组大小的习惯 - 这只是业余爱好者。
  • 我不想使用向量。我没有描述这种设计的原因是因为它与问题无关。我不确定我所问的是否可能,但如果是的话 - 我想知道如何按照我要求的方式去做。
  • @DanielCohen 如果您有特殊的要求阻止您使用普通 C++,您当然需要在问题中提及它们。我们还应该怎么回答?
  • @Quentin - 问题是,我怀疑这个问题是否存在“异国情调的要求”。异乎寻常的需求不会使malloc() 比使用标准容器更有效——因为大多数支持malloc() 的C++ 实现也有效地支持标准容器(及其默认分配器)。实际上,异乎寻常的要求更有可能导致使用具有非默认分配器的标准容器(例如,使用一些专用的非标准资源,例如共享内存)。

标签: c++ arrays visual-studio casting malloc


【解决方案1】:

根据您的 cmets,在我看来您想要类似的东西

template<typename T, std::size_t N>
struct array_wrapper {
    T array[N];
    // might extend with the remaining `std::array` interface
};

//...

auto array = std::make_unique<array_wrapper<TypeA, 0x10000>>();

some_library_function(array->array);

这样some_library_function 将看到一个类型为TypeA 和长度为0x10000 的内置数组,但具有动态存储持续时间。


请注意,我没有使用std::array,因为我不确定是否有一种有保证的合法方式可以从中获取对底层数组(而不是其第一个元素)的引用,即使使用reinterpret_cast 也是如此。如果TypeA 不是标准布局类型,至少可以肯定不会存在。


还要注意std::make_unique 将对数组进行值初始化,这意味着它将所有元素归零。如果您有一些特定的性能原因来避免这种情况,您可以在 C++20 或(不太理想)之前使用 std::make_unique_default_init 代替:

using array_type = array_wrapper<TypeA, 0x10000>;
auto array = std::unique_ptr<array_type>(new array_type);

【讨论】:

  • 这是正确的答案,尽管没有完全按照我的意愿去做。在询问之前我想到了这种方法,但后来决定值得询问是否可以进行我想要的演员 - 似乎它没有。
【解决方案2】:

与所有动态数组一样,使用std::vector

std::vector<TypeA> array(0x10000);

【讨论】:

    【解决方案3】:

    试试

    struct TypeA* array = malloc(0x10000 * sizeof(struct TypeA));
    

    编辑:对不起,这是 C

    【讨论】:

    • 那是C,问题标记为c++
    【解决方案4】:

    你不能有一个数组。 TypeA array[0x10000] 声明堆栈上的 0x10000 元素数组。结束。句号。

    但是,您可以在堆栈上拥有一个指向数组开头的指针。这是通常的做法:

    TypeA *array = (TypeA*)malloc(sizeof(TypeA)*0x10000);
    

    由于这是 C++ 而不是 C,因此您应该使用为此目的而存在的 new。请注意,如果TypeA 有构造函数,malloc 不会调用它,但new 会。

    TypeA *array = new TypeA[0x10000];
    

    不要忘记使用free(对于malloc)或delete [](对于new [])释放数组

    你也可以分配一个std::array:(这算作一个对象,所以用delete而不是delete[]删除它)

    std::array<TypeA, 0x10000> *array = new std::array<TypeA, 0x10000>;
    

    【讨论】:

    • 请不要使用原始拥有指针。使用std::vectorstd::unique_ptr
    • @Quentin 看门人?我认为每个人都应该在学习智能指针之前学习原始指针。然后,他们了解智能指针在做什么。
    • 只是提倡学习使用错误的语言不是先决条件。原始指针非常有用,不会因为毫无意义地拥有资源而破坏 RAII。
    • 这行不通。我希望sizeof(array) 返回实际大小
    • @DanielCohen 这绝对值得在问题中提及。
    猜你喜欢
    • 1970-01-01
    • 2014-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-08
    • 1970-01-01
    • 2019-11-17
    相关资源
    最近更新 更多