0

我有一个Foo来自外部 API 库的结构,它是 C 语言,在它之上我正在编写一个 C++ 接口。

所以我有这样的课:

class ClassFoo
{
public:
    ClassFoo(const Foo * ptr) : ptr(ptr) { }
    ~ClassFoo();

    bool method1();
    int method2();
    ... (other methods)
private:
    const Foo * ptr;
}

然后,外部库定义另一个struct BarFoos 的集合、获取 foo 数量的方法和检索Foo*指针数组的方法:

int APIbarGetNumFoos(const Bar* ref);
void APIbarGetFoos(const Bar* ref, int maxSize, const Foo* foos[]);

我这样定义ClassBar

class ClassBar
{
public:
    ClassBar(const Bar * ptr) : ptr(ptr) { }
    ~ClassBar();

    std::vector<ClassFoo> getFoos();

    ... (other methods)
private:
    const Bar * ptr;
}

现在的问题是:为了内存和速度效率,我想避免分配一个数组Foo*来调用 C API,然后将所有内容复制到结果向量中。

如果我不使用任何虚拟方法(以避免 vtables), C++ 是否保证ClassFoo实例只包含一个Foo*指针,并且它的大小是指针的大小,以便我可以这样定义getFoos()

std::vector<ClassFoo> ClassBar::getFoos()
{
    int size = APIbarGetNumFoos(ptr);
    std::vector<ClassFoo> result(size);
    APIbarGetFoos(ptr, size, (const Foo**) &result[0]);
    return result;
}

换句话说,我可以确定一个数组ClassFoo在内存中与一个数组完全相同Foo*吗?

谢谢!

艾蒂安

4

3 回答 3

3

您可以使用静态断言:

static_assert(sizeof(Foo*) == sizeof(ClassFoo), "Sizes don't match!");

然后,如果大小不匹配,您将遇到编译时错误。纯粹主义者可能会说这仍然不够严格,但在实践中可能还可以。

顺便说一句,这里:

(const Foo*) &result[0]

我想你的意思可能是:

reinterpret_cast<const Foo**>(&result[0]);
于 2013-05-30T11:00:06.953 回答
1

我相信简短的回答是:是的!

C++ 对象(不包含 vtables)就像 C 结构,方法就像带有隐式this参数的 C 函数。

如果您启用了 RTTI,我不确定这是否属实。

于 2013-05-30T11:00:35.537 回答
0

从回复和评论看来:

  • 它适用于最近的 gcc (4.8),并且似乎适用于主要编译器
  • 可以通过以下方式在编译时保证这一点:(在 gcc 4.8 上测试)

    static_assert(! std::is_pod<ClassFoo>::value, "Foo* cannot be copied to ClassFoo");

  • 它可能限制较少,仍然可以使用is_standard_layout,而不是is_pod

于 2013-05-30T13:40:20.897 回答