【问题标题】:Creating a C++ array that can be several types创建一个可以是多种类型的 C++ 数组
【发布时间】:2017-05-26 23:00:42
【问题描述】:

我有一个返回void* 的函数。现在,当这个函数完成时,一个UINT16*数组作为void*返回。 UINT16 数组是在方法开始时创建的,但现在我需要一种方法来确定数组的类型并改为创建该类型。例如,发生了一些数据处理,确定应该创建一个int类型的数组,所以创建并返回一个int数组。也可以创建其他类型,例如 double 和 byte。

我该如何实现这一目标?

我当前的代码有

UINT16* data_out = new UINT16[arraySize];   

我知道我可以创建一个大的 if/else 或 switch 语句,但我想知道是否有更好的方法。

【问题讨论】:

  • boost::variant 也许吧。
  • 如果您的问题只是if/else,请使用开关
  • 模板专业化
  • 您的问题不清楚。为什么不想使用if 语句?
  • 如果您的函数返回 void* 并且数组的类型是在您的函数内部确定的,那么您将遇到问题,因为在 C++ 中没有从 void* 进行隐式转换。因此,要使用函数返回的类型,您必须知道类型。

标签: c++ arrays pointers object if-statement


【解决方案1】:

大概是这样的吧?

这不起作用,但感谢您的支持。事实上它可以工作,但你必须知道Foo 返回的类型才能使用它。但是类型是在Foo 内部确定的,这是一个严重的概念缺陷。您应该重新考虑您希望它的工作方式。

    enum class ArrayType
    {
        Int,
        Double
    };

    template <typename T>
    T* CreateArray(size_t size)
    {
        T* t = new T[size];
        return t;
    }

    void* Foo(param1, param2, etc..)
    {
        size_t size;
        ArrayType type;

        .. Do things to determine the type

        switch(type)
        {
            case ArrayType::Int:
                return CreateArray<int>(size);

            case ArrayType::Double:
                return CreateArray<double>(size);

            default:
                return 0;
        }

        return 0;
    }

【讨论】:

    【解决方案2】:

    嗯...对不起,如果这更像是一个问题而不是评论...:|我无法评论 rn。

    如果您想要一个核心解决方案,您可以创建一个具有不同类型出口的链表类。基本上,您不会只有UINT_64* next;,而是:

    int* nextInt;
    double* nextDouble;
    

    等等等等。然后,如果你想标记一个 double,你可以使用 nextDouble 出口。要找到去哪个出口,只需检查 int 是否指向任何东西;如果没有,请继续。我知道这似乎是一个非常烦人且笨重的选项,但我想它可以完成这项工作。

    【讨论】:

      【解决方案3】:

      我不知道为什么你必须使用void* 来使用一个实际上没有类型的返回值,但让我们假设它是有原因的。

      其实有两个问题,一个是创建数组,然后是使用它。

      当基于某种逻辑创建不同类型的数组时,你必须以某种方式处理ifswitch();否则您将如何表达确定所需结果类型的逻辑?但是,如果您愿意,您也可以使用result = malloc(nrOfItems*sizeOfItem) 之类的东西,并根据您喜欢的任何逻辑确定sizeOfItem,甚至基于算术计算。

      更有趣或关键的是调用者应如何使用相应函数的结果,因为访问数组的元素需要了解其中元素的类型或大小。

      假设,例如,下面的代码:

      void* getSomeItems() {
        if (std::rand() > 100000)
          return new char[200];
        else
          return new double[200];
      }
      
      int main() {
        void* someItems = getSomeItems();
        double c = ((double*)someItems)[199];  // Critical!
        // how shall we know if element type is double?
        // if rand() decided to create items of type char,
        // this code accesses non allocated memory
        ...
      

      因此,除非您的函数可以返回有关已创建类型的信息(实际上还有数组的大小),否则返回值几乎是不必要的。

      我建议不要为此使用void*。如果您在调用函数之前知道类型,则可以使用模板、向量或其他东西。如果您在调用之前不知道类型和/或大小,则返回一个结构 - 除了分配的数组之外 - 还提供类型/大小信息。

      顺便说一句:不要忘记delete[] / free最后的结果。

      【讨论】:

        【解决方案4】:

        Void * functions can be fun and do some very interesting things...(很抱歉链接了我以前的答案,但这是我遇到的第一个示例。)但它们并不安全,并且 类型检查...

        因此,在您的情况下,您只需要一个简单的模板函数和 auto 关键字。比如:

        #include <iostream>
        #include <iomanip>
        
        template <typename T>
        T * returnAnArray (int size) {
            T * data_out = new T[size];
            return data_out;
        }
        
        int main() {
            int size = 3;
            auto array = returnAnArray<double>(3);
        
            for(int i=0;i<size;++i)
                array[i] = 0;
        
            for(int i=0;i<size;++i){
                std::cout << std::setprecision(2);
                std::cout << array[i] << std::endl;
            }
        
            delete [] array;
        
            return 0;
        }
        

        我确实有一些乐趣,并且确实创建了一个void * 函数:

        template <typename T>
        void * returnVoidPointerToArray(int size) {
            return new T[size];
        }
        

        该函数在使用时必须进行强制转换,因为它可能会返回一些东西:

        auto chArray = (char*)returnVoidPointerToArray<char>(size);
        

        但输出看起来像:

        5.00
        5.00
        5.00
        ggg 
        ggg 
        ggg 
        Program ended with exit code: 0
        

        注意双精度值是多少,但同样的函数也初始化了一个二维字符数组……很酷,对吧?尽管它是一种更脏、更不同的模板函数方式。

        而且,正如评论者所说,使用唯一指针可能是个好主意。 :)


        就像其他评论者所说,我将数组转换为 char* 并得到一个 char* 数组。 :)

        【讨论】:

        • "但是同一个函数似乎已经初始化了一个二维字符数组..." - 那是因为您将结果转换为char *,不是吗?
        猜你喜欢
        • 2022-06-15
        • 2017-01-01
        • 1970-01-01
        • 2015-03-01
        • 1970-01-01
        • 2020-03-31
        • 2017-08-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多