将一个 std::vector 对象转换为结构体数组

3
我有一个VS2008 C++程序,其中我正在封装一个C API以在C++程序中使用。如下所示,C API期望一个TABLE_ENTRY值数组。
除了从MyClassCollection :: GetTable()中的每个MyClass结构中复制数据到新的TABLE_ENTRY结构之外,是否有一种方法可以获得我正在寻找的功能?
谢谢, PaulH
struct TABLE_ENTRY {
    const char* description;
    DWORD value;
};

class MyClass
{
public:
    MyClass( const char* desc, DWORD value ) : 
        description( desc ),
        some_value( 1 )
    {
    };

    TABLE_ENTRY* GetTable()
    {
        entry_.description = description.c_str();
        entry_.value = some_value;
        return &entry_;
    };

    TABLE_ENTRY entry_;
    std::string description;
    DWORD some_value;
};

class MyClassCollection
{
public:
    TABLE_ENTRY* GetTable()
    {
        return collection_.front()->GetTable();
    };

    void Add( MyClass* my_class )
    {
        collection_.push_back( my_class );
    }
private:
    std::vector< MyClass* > collection_;
};

int _tmain( int argc, _TCHAR* argv[] )
{
    MyClass class1( "class1", 1 );
    MyClass class2( "class2", 2 );

    MyClassCollection collection;
    collection.Add( &class1 );
    collection.Add( &class2 );

    TABLE_ENTRY* table = collection.GetTable();

    // table is to be used by the C API. Therefore, these next
    // calls should function as shown.
    TABLE_ENTRY entry1 = table[ 0 ]; // should be class1's table (works)
    TABLE_ENTRY entry2 = table[ 1 ]; // should be class2's table (full of junk)

    return 0;
}
4个回答

1
获取一个数组:(C++03已经将其合法化,但是所有的C++98实现似乎也支持它)
&vec[0]

请注意,向量仍然拥有内容,因此不要删除内存或重新分配它。

哎呀...我昨天的每日声望上限还没解除,算了吧。 - Tronic
它也是合法的C++98。不幸的是,你不能获得一个不同对象类型的数组而不进行复制。 - Mike Seymour
这与我现在所做的 &vec->front() 相同。 - PaulH

1

我会选择将数据复制到一个vector<TABLE_ENTRY>中,并将&entries[0]传递给C API。

而且,我不会将TABLE_ENTRY存储在你的C++类中。我只会在调用API时创建它们,然后将它们丢弃。这是因为TABLE_ENTRY会复制你从中复制的对象,并且它存储了一个直接的char*指向由std::string管理内存的字符串。如果你修改源字符串(并导致重新分配),你就会有一个悬空指针。


我可以这样做,那会很容易。但是,那可能会产生很多副本,我宁愿避免。不过,你关于char*指针的观点很有道理。 - PaulH
嗯,偶尔我会写非常快的代码。从中我知道不到1%的代码库值得优化。其余的我都用“简单”的方式处理,这样我就可以更加努力地工作在那1%上。这可能是你的1%,但我没有看到任何有关速度应该有多快的数字,所以我认为不是。 - user180326
这并不是必须要快速完成,只是我希望能找到一种更优雅的方法。如果找不到,也没关系。你可能认为这是浪费我的时间,但如果我能找到一个解决方案,那么我可以将其应用于未来,并使我的未来代码变得更好。 - PaulH

0
如果你的字段是完全相同的(string != char*),你可以将对象转换为void*,然后通过一些偏移量将其转换为结构体(以跳过VMT和其他面向对象的东西)。

是的,但这会对类中对象的顺序和位置施加一定的限制。如果可能的话,我想避免这种情况。 - PaulH
如果您想要定制顺序,可以创建一个函数将您的对象转换为结构体。 - Andrey
上面代码中的 MyClass::GetTable() 函数类似这样的吗? - PaulH

0
通过请求一个TABLE_ENTRY数组,API让您知道它期望数据以特定的方式在内存中排列。没有办法用不同的方式满足API的期望,所以你只能凑合着了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接