簡體   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