繁体   English   中英

在C ++函数中传递原始数据类型的最佳实践

[英]Best practice for passing primitive data type in C++ function

我正在为avr芯片编写一个函数,将字节流反序列化为基本类型。 我想以尽可能通用的方式进行,并且想知道确定反序列化类型的最佳实践是什么。 我到目前为止的想法包括:

选择A:

// Just write a function for each type
double deserialize_double(uint8_t *in) { }

选择B:

// Use a template, and pass the type in when calling
// Function:
template <typename TYPE>
TYPE deserialize(uint8_t *in) {
  union {
    TYPE real;
    uint8_t base[sizeof(TYPE)];
  } u;

  for (unsigned int i = 0; i < sizeof(TYPE); i++) {
    u.base[i] = in[i];
  }
  return u.real;
}

// Call:
double value = deserialize<double>(in);

选择C:

// Similar to B, but you pass in the type as a parameter
// Function:
TYPE deserialize(uint8_t *in, TYPE);

// Call:
double value = deserialize(in, double);

选择D:

// Use a templated class. My main issue with this is I was hoping 
// to re-use the same object for deserializing multiple types.
template <typename TYPE>
class Serializer {
  public void serialize(uint8_t *out, TYPE value) { /* code */ }
  public TYPE deserialize(uint8_t *int) { /* code */ }
};

有关最佳方法的任何想法吗? 也许我忽略了一种更简单的方法。

对于初学者,C和D是无效选项,因为类型不是有效的函数参数; 不妨现在就把它们排除在外。

选择B在这里似乎是明显的赢家,假设您不关心字节排序或其他使用联合的潜在警告(看起来您不会得到这项工作的背景)。

另外需要考虑的是在反序列化时使用一些反馈机制来推进字节流指针/索引。 也许你可以试试像

template <typename TYPE>
int deserialize(uint8_t *in, TYPE& value) {
    union {
        TYPE real;
        uint8_t base[sizeof(TYPE)];
    } u;

    for (unsigned int i = 0; i < sizeof(TYPE); i++) {
        u.base[i] = in[i];
    }
    value = u.real;
    return sizeof(TYPE);
}

// Call:
double foo, bar;
int baz;
in += deserialize(in, foo);   // Implicit double deserialize
in += deserialize(in, bar);   // Implicit double deserialize
in += deserialize(in, baz);   // Implicit int deserialize

这有额外的优势(正如我看到@Asha已经打败了我!)允许你利用C ++模板的类型推理系统; 由于第二个参数在调用位置具有已知类型,因此无需为TYPE显式指定模板参数。

还有一个选项是将结果作为“out”参数返回。 在这种情况下,您无需在模板实例化期间指定类型。 像这样的东西:

template <typename TYPE>
void deserialize(uint8_t *in, TYPE& out) {
  union {
    TYPE real;
    uint8_t base[sizeof(TYPE)];
  } u;

  for (unsigned int i = 0; i < sizeof(TYPE); i++) {
    u.base[i] = in[i];
  }
  out = u.real;
  return;
}

// Call:
double value = 0;
deserialize(in, value);

提醒一句:

由于多种原因,通常不建议将C ++用于AVR,并且有些事情根本不会起作用 - 因此在将任何特定时间放在任何特定时间之前,请小心测试目标芯片上的代码路径。

但这并不意味着你必须放弃任何重要的功能。 只需调整您的代码以适应可用的语言功能。

在我看来, 选择B是最好的。 它增加了可读性和易用性。 而且,TYPE可以是一些更大的类/结构吗? 因为您是通过deserialize()方法按值返回的!

您应该使用选择A,因为:

  1. 它引入了最少的复杂性。
  2. 与C和C ++兼容。
  3. 如果不支持该类型,则提供直接行为。

请注意,如果您需要选择B的语法,则始终可以在以后的日期(通过为不同类型提供特化)的代码之上实现该选项。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM