Does the standard provide a guarantee that adding a constructor won't resize?

Let's say I have a class

struct Foo {
    uint32_t x;
    uint32_t y;
};

      

The C ++ standard mentions should it sizeof(Foo)

be the same as sizeof(Bar)

if it Bar

just adds a constructor?

struct Bar {
    uint32_t x;
    uint32_t y;
    Bar(uint32_t a = 1,uint32_t b = 2) : x(a),y(b) {}
};

      

The reason I am asking is because it is Foo

sent over the net as void*

and I cannot resize it, but I would like to add a constructor if possible.

I found several related ones: here and here , but there the answers focus mainly on virtual changes and I was looking for something more specific than "[...] all the implementations I know of [...]" .

PS: To avoid confusion ... I am not asking how to constsruct a Foo

and then posting it as void*

, and I am not asking for a workaround to make sure the size does not change, but I am really just curious if the standard knows anything oh sizeof

in this particular case.

+3


source to share


3 answers


C ++ 98 only guarantees layout for "plain old data" objects, and they don't allow constructors to be created.



C ++ 11 introduces " standard layout types " that still guarantee layout but allow constructors and methods to be added (and allows virtual bases to be added with some exceptions for empty classes and duplicates).

+4




Actually, the only thing that affects the layout is the data contained in the object, with one important exception that comes to this later. If you add any functions (and constructors are really nothing more than some kind of static function with only special syntax), you won't affect the class layout.

If you have a virtual class (a function with at least one virtual function, including a virtual destructor), your class will contain an entry in the vtable (this is not done in the standard, but in a standard way, like polymorphism), but this is just a pointer to a specific scope memory elsewhere. The virtual table itself will be modified if you add more virtual functions, but without any impact on the layout of your data containers (they are actually instances of the class).

Now the exception mentioned above: If you add a virtual function to a class (or create an existing virtual one, including a destructor), while the class didn't have virtual functions before (i.e. no virtual functions of its own and no inherited ones!) ,. then vtable will be added and then data format will change! (Likewise, the vtable pointer is deleted if you make all functions non-virtual - including all inherited ones).

Is it guaranteed by the standard?

Edit:

From the C ++ standard, section 4.5 C ++ Object Model (Β§ 1):

[...] Note. A function is not an object, whether or not it takes up storage the way objects do. - end of note [...]

Next is the conclusion (mine): a function (note: undifferentiated if free or member) is not an object, therefore it cannot be a subobject, therefore it is not part of the object's data.



Further (the same Β§):

The object is of type (6.9). Some objects are polymorphic (13.3); the implementation generates information associated with each such object, which allows the type of objects to be determined at runtime.

(These are vtables!) - note that it is not explicit about how they are implemented, doesn't even apply them at all, if the compiler vendor finds some alternative, he can use it ...).

For other objects, the interpretation of values ​​found there is determined by the type of expressions (clause 8) used to access them.

Well, haven't been able to find any hints (yet) if and how functions affect the class layout, rather than fly over the standard in general, and not (with special attendance) in chapters 8 (as mentioned above) or 12 "classes" (especially 12.2 "members of the class").

It doesn't seem to be explicitly stated (won't keep my hand on fire for not being in control though ...). Perhaps it is fair to deduce this already from functions that are not exclusively objects ...

The standard layout classes referenced by Jan Gusek provide additional layout guarantees such as member reordering (which is allowed for members of varying accessibility), alignment conditions, ...

From these conditions for being an SLC, I go that at least a guarantee applies for them, since everything referenced for layout compatibility is data members, no functions (non-static members) are mentioned (other than no virtual are allowed ...).

+1


source


As explained by other answers, the layout can change if a virtual destructor is added.

If your destructor is not virtual, you can go ahead and add. But say you want a virtual destructor, you can wrap the structure in another structure and put the destructor in there.

Make sure the fields you want to change are available to the wrapper class. The attitude of friends should be good enough.

All your inheritance will go through the shell though. The internal structure is just the layout support so you can send it over the net.

0


source







All Articles