简体   繁体   English

C ++和压缩结构

[英]C++ and packed struct

I have database project that I want to move from C to C++. 我有数据库项目,我想从C转移到C ++。 In this C project I have lots of small packed structs, that I write directly to file or read from mmaped file - eg directly from memory address. 在这个C项目中,我有许多小的打包结构,我直接写入文件或从mmaped文件中读取 - 例如直接从内存地址。

I need the class in-memory representation, to be exactlybthe same as if I use plain old C struct. 我需要类内存表示,与我使用普通的旧C结构完全相同。 I believe this is called POD or C++ standard layout. 我相信这称为POD或C ++标准布局。

I can proceed in several ways: 我可以通过以下几种方式进行:

I can do class, bu I worry that if I add methods to this struct, probably the internal structure will be changed. 我可以上课,但我担心如果我向这个结构添加方法,可能会改变内部结构。

If I wrap the a structure into class, I will need to create / destroy classes all the time, along with the structs. 如果我将一个结构包装到类中,我将需要一直创建/销毁类,以及结构。

If I do it C - OO style, I will need to supply pointer to every function, eg 如果我做C - OO样式,我将需要提供指向每个函数的指针,例如

static const char *Pair::getKey(const void *mem);

I can also make the struct a field and do something similar 我也可以将结构化为字段并执行类似的操作

void Pair::setMem(const void *mem);
const char *Pair::getKey();

but the more I see this, the less I like it, because there is no real advantage. 但我越是看到这个,我就越不喜欢它,因为没有真正的优势。

Anything I am missing? 我错过了什么?

If I add methods to this struct, probably the internal structure will be changed. 如果我向这个结构添加方法,可能会改变内部结构。

That's wrong; 那是错的; to satisfy your needs what you want is to keep your structure a POD, for which essentially you don't want: 为了满足您的需求,您希望将结构保持为POD,基本上您不需要:

  • non-trivial constructors/destructors/assignment operators; 非平凡的构造函数/析构函数/赋值运算符;
  • virtual functions or virtual base classes; 虚函数或虚基类;
  • different access specifiers for data members . 数据成员的不同访问说明符。

(there are some additional restrictions (see C++11 §9 ¶6-10), but they are not particularly relevant in your case) (还有一些额外的限制(参见C ++11§9¶6-10),但它们在你的情况下并不是特别相关)

The "POD" thing implies two things: “POD”事情意味着两件事:

  • that your class is "standard layout", which roughly means "laid out in a well-defined manner, the same way as C would do" (which assesses your primary concern); 你的班级是“标准布局”,大致意思是“以明确的方式布局,就像C一样”(评估你的主要关注点);

    adding methods shouldn't break stuff, since, as they aren't be virtual, they are translated as free functions which take a pointer to the object as hidden parameter, and that requires no modification to the original C layout. 添加方法不应该破坏东西,因为它们不是虚拟的,它们被翻译为自由函数,它将指向对象的指针作为隐藏参数,并且不需要修改原始C布局。 static methods are just free functions with different scoping, so in general they are a non-issue. static方法只是具有不同范围的自由函数,因此通常它们不是问题。

  • that your class can be freely copyable with a memcpy without stuff breaking, which is probably what you want if you read it straight from file (either with mmap or with fread ); 你的课程可以用memcpy自由复制而不会破坏,这可能是你想要的,如果你直接从文件中读取它(使用mmapfread );

    this is accounted for by the "triviality" of the constructors (ie if they are skipped nothing bad happens to your objects) and by the absence of virtual members, which means that you don't risk overwriting the vptr with a stale one read from the file. 这是由构造函数的“琐碎性”(即如果它们被跳过,对象没有发生任何坏事)以及缺少虚拟成员所占,这意味着你不会冒险用一个陈旧的读取来覆盖vptr文件。

C++11 has a specific concept called standard layout, it basically means that for classes meeting the standard layout requirements, it guarantees that the class will be laid out in memory identically to C. The requirements are: C ++ 11有一个称为标准布局的特定概念,它基本上意味着对于满足标准布局要求的类,它保证类将在与C相同的内存中布局。要求是:

  • All non-static data members have the same access control 所有非静态数据成员都具有相同的访问控制
  • Has no virtual functions or virtual base classes 没有虚函数或虚基类
  • All non-static data members and base classes are themselves standard layout types 所有非静态数据成员和基类本身都是标准布局类型
  • Has no two base class subobjects of the same type 没有两个相同类型的基类子对象

So you can add methods to your classes, as long as you're careful. 所以只要你小心,你就可以为你的类添加方法。 See http://en.cppreference.com/w/cpp/concept/StandardLayoutType . 请参见http://en.cppreference.com/w/cpp/concept/StandardLayoutType

If I add methods to this struct, probably the internal structure will be changed. 如果我向这个结构添加方法,可能会改变内部结构。

This is unlikely, at least no more so than changing compiler (from C to C++). 这不太可能,至少不会改变编译器(从C到C ++)。 You can add methods, as long as they aren't constructors, destructors, assignment operators, or virtual functions, and the memory layout is guaranteed to not change. 您可以添加方法,只要它们不是构造函数,析构函数,赋值运算符或虚函数,并且保证内存布局不会更改。

For more information, see Structure of a C++ Object in Memory Vs a Struct 有关更多信息,请参阅内存中的C ++对象的结构和结构

If I wrap the structure into class, I will need to create / destroy classes all the time. 如果我将结构包装到类中,我将需要始终创建/销毁类。

Which is exactly the same as creating and destroying structs all the time. 这与创建和销毁结构始终完全相同。 Class instantiation in C++ consists of a memory allocation and a call to a constructor. C ++中的类实例化包括内存分配和对构造函数的调用。 You have the same control over the allocation as you do with a struct, and you control all of the code in the constructor (including the option to have no code at all). 您对分配的控制与对结构的控制相同,并且您可以控制构造函数中的所有代码(包括根本没有代码的选项)。

It is perfectly legal to write C code and build it using a C++ compiler. 编写C代码并使用C ++编译器构建它是完全合法的。 It is also possible to write C++ code (under a few restrictions) that compiles to exactly the same binary as that C code. 也可以编写C ++代码(在一些限制下),编译与C代码完全相同的二进制文件。 What using class/struct members gets you is a (arguably) cleaner syntax and implied currying of the this pointer. 使用类/结构成员获取的是一种(可以说是)更清晰的语法,并暗示了this指针的干扰。 For example: 例如:

// C
ret = CallMyStructMethodX(pMyStruct, param1, param2);

// C++
ret = pMyStruct->CallMethodX(param1, param2);

These two lines of code will are identical. 这两行代码是相同的。 The only difference is that in the latter case, your struct pointer is passed by the implied this parameter, rather than as an explicit parameter to the function. 唯一的区别是,在后一种情况下,结构指针由隐含的this参数传递,而不是作为函数的显式参数传递。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM