【问题标题】:Is there a C++ equivalent of java.lang.Number?是否有与 java.lang.Number 等效的 C++?
【发布时间】:2017-01-01 11:01:49
【问题描述】:

我正在尝试创建一个std::vector,它可以在 C++ 中接受任何类型的数字数据类型(char、short、int、long、float 和 double)。

在java中,我可以创建List<Number> list = ArrayList<Number>();

在 C++ 中是否有等价物(最好是

PS - 我真的不希望每种数据类型都有一个向量:/

【问题讨论】:

  • 类型擦除怎么样?
  • 工会也许适合你。
  • 您不能将不同大小的元素存储在向量中。无论是在 C++ 中还是在 Java 中。在这种情况下,Java 实际上存储了实际对象的引用。因此,您还必须为每个条目存储 64 位。在 C++ 中你可以使用指针,但我不确定这是否值得。
  • 你可以把联合本身放在向量中。在 Java 中,您可以使用 Number,但请记住 Number 是对象,每个对象增加 8 个字节的开销,然后是 4 个字节用于引用。添加填充,Java 中装箱的“8 位整数”需要 16 字节 + 4 字节作为参考 = 160 位(在 32 位 Java 上;在 64 位上更糟)。 C++ union 仍然大获全胜。

标签: java c++ inheritance vector type-conversion


【解决方案1】:

你想要的一个简单的方法是:

enum datatype
{
    dt_none,
    dt_char,
    dt_uchar,
    dt_short,
    dt_ushort,
    dt_long,
    dt_ulong,
    dt_float,
    dt_double
};

struct Any
{
      datatype type; // To know what is stored inside union, not mandatory if you know that in another way
      union
      {
          char vchar;
          unsigned char vuchar;
          short vshort;
          unsigned short vushort;
          long vlong;
          unsigned long vulong;
          float vfloat;
          double vdouble;
      } data;
};

std::vector<Any> mydata;

您可以避免使用联合,但它会占用更多内存(每个值的指针 + 实际大小)并且使用起来更复杂:

struct Any
{
     private:
         void * data;
         datatype type;

     public:
         Any():
             data(NULL),
             type(dt_none)
         {}

         ~Any()
         {
             deleteData();  
         }

         void deleteData()
         {
             // Because deleting a void * is UB, we have to check real datatype
             if (data != NULL)
             {
                 if (type == dt_char)
                     delete static_cast<char *>(data);
                 if (type == dt_uchar)
                     delete static_cast<unsigned char *>(data);
                 ....
             }   
         }

         datatype getType() const
         {
             return type;
         }

         void setChar(char v)
         {
             deleteData(); 
             data = new char(v);
             type = dt_char;
         } 


         char toChar() const
         {
             return *static_cast<char *>(data);
         } 

         .....

         void setDouble(double v)
         {
             deleteData();
             data = new double(v);
         }

         double toDouble() const
         {
             return *static_cast<double*>(data);
         }
};

一个可能的优化是使用指针来存储小类型数据,以节省一些字节(但要小心!)。但是如果你存储了大量的大类型数据,union 还是更好的。此外,指针的大小取决于平台,因此很难选择哪种类型可以直接存储在指针中并具有可移植的代码。此外,在 64 位计算机上,指针的大小为 8 字节,这也是 double 的常见大小(所以,在这种情况下,将每种类型直接存储在指针中,这与 union 的内存消耗相同,但实际上更多复杂且不安全的方式):

struct Any
{
     private:
         void * data;
         datatype type;

     public:
         Any():
             data(NULL),
             type(dt_none)
         {}

         ~Any()
         {
             deleteData();
         }

         void deleteData()
         {
             // Because deleting a void * is UB, we have to check real datatype
             if (type != dt_char && type != dt_uchar && data != NULL)
             {
                 if (type == dt_double)
                     delete static_cast<double *>(data);
                 ....
             } 
             data = NULL;
         }

         datatype getType() const
         {
             return type;
         }

         void setChar(char v)
         {
             data = reinterpret_cast<void *>(v);
         } 


         char toChar() const
         {
             return static_cast<char>(reinterpret_cast<intptr_t>(data));
         } 

         .....

         void setDouble(double v)
         {
             deleteData();
             data = new double(v);
         }

         double toDouble() const
         {
             return *static_cast<double*>(data);
         }
};

也就是说,您的情况只有 2 个简单的解决方案(恕我直言):

  • 如果你真的想节省内存,你必须为每种类型使用一个向量。
  • 或使用union

PS:你也可以看看第三方库,比如boost::any

【讨论】:

    猜你喜欢
    • 2021-04-30
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-06
    • 2010-12-23
    • 2011-07-14
    相关资源
    最近更新 更多