【问题标题】:Reinterpret-cast of pointer to array of objects重新解释指向对象数组的指针
【发布时间】:2018-01-03 07:03:55
【问题描述】:

我想围绕以下 C API 编写简单的 C++ 包装(用于 RAII 目的):

typedef void* T;

T createT(Arg arg);
int foo(T t);
closeT(T t);
int bar(const T* ptrToArrayOfT, unsigned long size);

前三个函数很简单(为了简短起见,我省略了检查错误和抛出异常):

class C {
public:
  C(Arg arg) : t_(createT(arg)) {}
  ~C() { closeT(t_); }
  int doFoo() { return foo(t_); }
private:
  T t_;
}

至于bar,我希望具有以下签名的功能:

int doBar(const vector<C>& vec);

这是我正在考虑的实现方式:

int doBar(const vector<C>& vec) {
  static_assert(sizeof(C) == sizeof(T));
  return bar(reinterpret_cast<const T*>(vec.data()), vec.size());
}

这样做安全吗? (我怀疑是因为C 有私人成员)。如果不是,那么有没有办法在不给出t_C 成员的情况下实现bar()? (不需要使用矢量)。

【问题讨论】:

  • 静态断言没有意义,因为T被定义为void*
  • @BartekBanachewicz,我不断言T 指向的大小。我断言C 的大小与void* 完全相同。
  • bar 函数的用途是什么?
  • @Holt,这有多重要?好的,它有点等待来自 T 指向的对象的信号,并返回发出信号的那个的索引。但不管它做什么,我自己无法实现它的功能,我必须形成一个T 的数组并将其传递给bar
  • @DmitryJ 没错。但是根据标准sizeof(void *)(请记住typedef void* T;)是未定义的。

标签: c++ reinterpret-cast


【解决方案1】:

不,此代码不安全,违反了strict aliasing

例如,您可以轻松编写此代码,而无需访问 t_

int doBar(const vector<C>& vec) {
  std::vector<const T> ts();
  ts.reserve(vec.size());
  for (auto c : vec) {
     ts.emplace_back(c.t_);
  }
  return bar(ts.data(), ts.size());
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-21
    • 2016-12-23
    • 2012-03-09
    • 1970-01-01
    • 2017-12-26
    • 1970-01-01
    • 1970-01-01
    • 2014-01-26
    相关资源
    最近更新 更多