【问题标题】:Cast of pointer to vector of different types指向不同类型向量的指针转换
【发布时间】:2013-07-21 19:42:11
【问题描述】:

我有一个函数需要一个指向uint16_t 类型向量的指针。该函数用数据填充向量。我还有应该保存数据的对象,但是以uint8_t 类型的向量的形式。我的代码如下所示:

void fill1(vector<uint16_t> *data);
void fill2(vector<uint64_t> *data);

class Object
{
    uint32_t data_depth;
    vector<uint8_t> data;
}

Object object1;
object1.data_depth = 16;
fill1((vector<uint16_t>*) &object1.data);

Object object2;
object2.data_depth = 64;
fill2(vector<uint64_t>*) &object2.data);

// somewhere later in the code
if (object1.data_depth == 16)
   vector<uin16_t> * v = (vector<uint16_t>)(&objec1.data);

是不同类型向量指针转换的保存方式吗?

【问题讨论】:

  • 我很确定这是个坏主意。为什么不填充Object的成员函数?
  • 不安全。这是错误的,因为向量包含原始数据之外的其他信息
  • 我认为解决此问题的最佳方法是将数据从 uint16 复制到另一个 uint8(反之亦然),同时在需要时为每个元素执行从一种类型到另一种类型的实际数据转换,我donno 我自己(所以你实际上不是在复制,你是在旧数据的基础上创建新数据)
  • 我使用向量 来保存原始信息。其实我忘了说对象本身知道数据深度是16位。因此,当我要访问 Object 的数据时,我会将其处理为 16 位值。
  • 目前尚不清楚您要在这里完成什么。您是否尝试存储原始字节并将它们作为单个字节访问,或者您是否尝试将 16 位值存储在 8 位向量中(这会导致截断)?无论哪种方式,转换向量肯定是错误的。您可以通过转换底层数组指针来摆脱它。

标签: c++ pointers vector casting


【解决方案1】:

你可能会这样做:

template <typename T>
void fill(vector<unsigned char>& data)
{
    assert(data.size() % sizeof(T) == 0);

    T* pReinterpreted = reinterpret_cast<T*>(&data[0]);
    size_t count = data.size() / sizeof(T);

    // do some stuff with your array of reinterpreted values
}

class Object
{
    uint32_t data_depth;
    vector<unsigned char> data;
}

Object object;
fill<uint16_t>(object.data);

当然,这是不安全的代码,所以我不会这样做,除非你确切地知道这里的权衡是什么。

【讨论】:

  • 您可能应该使用unsigned char 而不是uint8_t,以遵守别名规则。但是,是的,转换第一个(或任何)元素的地址是正确的方法。
  • 是的,仔细想想,你不能真的有一个通用的填充,然后在函数内部使用 uint16_t*。
  • 如果fill 是一个模板,并且您使用了T*,则可以,其中T 可以是uint16_t 或任何其他原始类型。
  • 您忘记从通话中删除data_depth
  • 在这种情况下,您必须进行复制。将 vector 重新解释为 vector 是不安全的。你可能会非常(不)幸运并且让它在一些编译器上工作,但如果有任何保证这样的东西在一般情况下可以工作,我会感到惊讶。但是,您可以保证向量连续存储其元素,因此获取第一项的地址会为您提供 uint8_t 数组。如果您无法从 vector 更改源类型,则任何解决方案都必须以此为基础。
【解决方案2】:

这不安全。从根本上讲,向量不是该类型的数组,而是包含一些数据的对象,包括是指向该类型数组的指针。你做的那个演员会导致对额外数据的误解。实际上,您甚至不能保证 vector 的实现不依赖于类型(我怀疑这在任何地方都可以完成 - 除了 vector&lt;bool&gt; 之外 必须 以不同的方式实现——但绝对允许,只要所有单独的实现都符合标准)。

您可以使用boost::variant 允许将不同基本类型的向量存储在Object::data 中。

您的代码可能如下所示:

#include <boost/variant.hpp>

class Object
{
  boost::variant<std::vector<uint16_t>, std::vector<uint64_t> > data;
};

struct fill_visitor: boost::static_visitor<>
{
  template<typename T>
   void operator()(std::vector<T>& v)
  {
    fill(&v);
  }
};

// ...

boost::apply_visitor(fill_visitor(), object1.data);

【讨论】:

    猜你喜欢
    • 2011-12-29
    • 1970-01-01
    • 2012-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-04
    • 1970-01-01
    相关资源
    最近更新 更多