【问题标题】:2d float** or double** array runtime2d float** 或 double** 数组运行时
【发布时间】:2020-07-15 15:05:36
【问题描述】:

我必须创建一个名为 m2DArray 的数组。它有 2 行和 5 列,即 [2][5] 的大小。

数组可以是float**double**,我只在运行时才知道。

由于我在编译时不知道类型,所以我在头文件中将其初始化为

void **m2DArray;

然后我创建一个模板函数:

template <typename SampleType>
void MyClass::initiliaze2DArray(SampleType** m2DArrayTyped)
{
    m2DArray = new SampleType* [2]; //2 rows
    int32 sizeOfOneCol =  5 * sizeof(SampleType); // 5 cols
    for (int32 row = 0; row < 2; row++)
    {
        m2DArray[row] = new  SampleType [sizeOfOneColumn];
    memset(m2DArray[row], 0, sizeOfOneCol);
    }
}

然后在运行时,我根据类中的一些逻辑在 float** 或 double** 之间做出选择,并相应地尝试初始化 2d 数组。

if (somelogictellsfloat){
   float **mArrayFloat;
   initiliaze2DArray(mArrayFloat);
} 
else {
   double **mArrayDouble;
   initiliaze2DArray(mArrayDouble);
}

但是,当尝试初始化这个二维数组时,我无法在模板函数中将 void** 转换为 float** 或 double**。

我收到以下错误:

错误:在 m2DArray = new SampleType* [2] 行中从“double**”到“void**”的无效转换;

我的问题:

如何将 **m2DArray 从 void ** 转换为 float ** 或 double ** ?或者有没有更好的方法在运行时创建这个二维数组。

【问题讨论】:

  • 有什么理由不能使用包装类,比如template&lt;typename SampleType&gt; class Array2D?如果对象必须从一开始就存在,则创建一些接口Array2DBase,模板类从该接口继承并创建指向该接口的指针。
  • @Aziuth 谢谢,我不能使用类模板,因为它是更大代码库的一部分,我真的没有那种独立性来修改类以使用模板。
  • 另外,m2DArray是一个全局变量吗?如果是这样,尝试重写它,无论如何都是邪恶的。编辑:啊,好吧,你必须使用的其他代码,明白了。
  • 我想到了一个union,或者(更好)一个std::variant(但后者已经在C++17中引入)。
  • @bhaskarc if (typeisFloat) { RunMyApp&lt;float&gt;(argc, argv); } else {RunMyApp&lt;double&gt;(argc, argv); } -- 你考虑过吗? RunMyApp 是一个模板函数,基本上就是你的应用程序。如果你这样做了,void** 就没有必要了。

标签: c++ arrays c++11


【解决方案1】:

你这里有一些误解。最重要的是:void** 不是通用指针。唯一的通用指针是void*。因此,您的类型void** 可以包含通用void* 的地址。这是你需要了解的。

因此,无论您的数组有多少维,您都可以将其分配给void*。稍后,您有责任将其转换为您需要的类型。见:

    // Create a 5 dimensional array
    char***** dimension5 = static_cast<char*****>( malloc(200));    
    // Assign it to a generic pointer
    void* generic = dimension5;                                     
    // Get the address of the generic pointer
    void** addressOfGeneric = &generic;
    // Now dereference the address of the generic pointer to get back the generic pointer 
    // and cast it to our original type
    char***** dimension5Later = static_cast<char*****>(*addressOfGeneric);
    // Do something with the array
    dimension5Later[0][0][0][0][0] = 'H';

但是,我们当然不会那样做。在 C++ 中,我们永远不应该对拥有的内存使用原始指针。我们应该尽量避免使用原始指针并使用智能指针。我们不能使用malloc,我们甚至不应该使用new,而是使用一些make_unique-function。

我想知道,如果你需要它。因为你应该改用std::vector

请看以下内容:

    // The dimension of our 2d vector
    constexpr size_t NumberOfRows = 2U;
    constexpr size_t NumberOfColumns = 5U;
    bool somelogictellsfloat{ true };

    // Depending on what to create
    if (somelogictellsfloat) {

        // Create and initialize a 2d vector for floats
        std::vector<std::vector<float>> mArrayFloat(NumberOfRows, std::vector<float>(NumberOfColumns, 0.0));
    }
    else {
        // Create and initialize a 2d vector for doubles
        std::vector<std::vector<double>> mArrayDouble(NumberOfRows, std::vector<double>(NumberOfColumns, 0.0));
    }

但您真正想要的是使用抽象工厂模式。如果您不知道,请阅读此内容。

顺便说一句。我为您的原始代码制作了一个最小可重现的示例。在关于 SO 的问题中,您应该始终这样做。

我修复了一些错误并使其可编译。但请不要使用

#include <cstring>
#include < cstdlib >
#include <vector>

struct MyClass {

    void** m2DArray;   // Address of a generic pointer
    void* md;
    float** mArrayFloat;
    double** mArrayDouble;
    using int32 = int;

    template <typename SampleType>
    void initiliaze2DArray(SampleType** m2DArrayTyped)
    {
        m2DArrayTyped = new SampleType * [2]; //2 rows
        int32 sizeOfOneCol = 5 * sizeof(SampleType); // 5 cols
        for (int32 row = 0; row < 2; row++)
        {
            m2DArrayTyped[row] = new  SampleType[5];
            memset(m2DArrayTyped[row], 0, sizeOfOneCol);
        }
        md = m2DArrayTyped; // md is now a generic pointer 
        m2DArray = &md;     // and m2DArray is the address of that generic pointer
    }
    // Test function
    void test(bool doFloatAndNotDouble) {
        if (doFloatAndNotDouble) {
            initiliaze2DArray(mArrayFloat);
        }
        else {
            initiliaze2DArray(mArrayDouble);
        }
    }
};
// Driver code
int main() {

    MyClass mc{};
    mc.test(true);
    mc.test(false);
    return 0;
}



【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-09
    • 1970-01-01
    • 2011-05-28
    • 1970-01-01
    • 1970-01-01
    • 2012-06-08
    • 2020-08-07
    相关资源
    最近更新 更多