Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Do member `const`s save memory?



  • Idle question, just because I'm interested.

    Let's say I declare member variable of

    char fred[1024] = "abc";
    

    I am very well aware I am not using, say, QString here, else it wouldn't be an issue!

    Now, this should cost 1024 bytes of memory in each instance I create.

    If I changed to, say,

    static fred[1024] /*= "abc" */;
    

    that would now only cost me 1024 bytes once, regardless of instances.

    Question: if I declare as:

    const char fred[1024] = "abc";
    

    can I assume that the compiler will say to itself "it's const so I do not need to allocate in each instance, I can share one (read-only) occurrence between all instances", or not?


  • Lifetime Qt Champion

    @JonB said in Do member `const`s save memory?:

    I do not need to allocate in each instance,

    const only tells the compiler that the data can not be modified afterwards, the memory needs to be allocated and initialized anyway for each call (on the stack in your example so it's very fast)


  • Lifetime Qt Champion

    @JonB said in Do member `const`s save memory?:

    I do not need to allocate in each instance,

    const only tells the compiler that the data can not be modified afterwards, the memory needs to be allocated and initialized anyway for each call (on the stack in your example so it's very fast)


  • Lifetime Qt Champion

    @JonB said in Do member `const`s save memory?:

    can I assume

    I don't think so.
    And you should not assume if it is important - make it explicit (static in this case).


  • Moderators

    @JonB said in Do member `const`s save memory?:

    can I assume that the compiler will say to itself "it's const so I do not need to allocate in each instance, I can share one (read-only) occurrence between all instances", or not?

    I can't say for sure, but my I would say no, no optimisation in that regard,

    however

    constexpr char fred[1024] = "abc";
    

    should work in that way.


  • Lifetime Qt Champion

    @J-Hilk said in Do member `const`s save memory?:

    should work in that way.

    No, since it's created on the stack :)
    https://godbolt.org/z/1Yjajd81a


  • Moderators

    @Christian-Ehrlicher
    thats unfortunate. 😮‍💨



  • @Christian-Ehrlicher said in Do member `const`s save memory?:

    (on the stack in your example so it's very fast)

    Indeed, but the question is about memory. For the sake of argument, if I have 1,024 instances alive at the same time it would cost 1MB of stack memory, even if that's not a lot. As I say, it was just a question of interest.

    [Oh, BTW, you said "on the stack", but that's only if my instances are on the stack. If I new them it's occupying space on the heap, surely?]

    Anyway, it's interesting to understand that compilers would not somehow share but would allocate per instance, I get it, thanks.


  • Moderators

    @JonB wrap it in a constexpr getter :D

    https://godbolt.org/z/h4d6beMvs


  • Moderators

    I know it's marked solved but just wanted to point something out.

    When it's a class member it influences class layout i.e. things like sizeof, offsetof and member padding. Compiler can't rearrange class members or share them across instances because that would break the instance. For example if you get a pointer to the instance, cast to say char* and start iterating up to the sizeof through that memory you should see all the bytes of that array being there, otherwise C++ would be completely broken.

    If you don't want to modify it use const char* fred = "abc" instead of an array. This way only the pointer is part of class layout and you only pay for duplicating that. The data is stored elsewhere and thus can be shared (and is if you use any compiler that's half decent).



  • @Chris-Kawa , @J-Hilk
    First, may I say I am well aware of how, say, char * or constexpr would have worked instead. I picked the example I did (silly as it is) precisely because it is not one of those type of constructs,

    Yes, thinking it through I did appreciate about it must be a properly-allocated member of the class in each instance. So I do get why.

    When it's a class member it influences class layout
    and start iterating up to the sizeof through that memory

    I assumed that one would be shot if trying to look through the layout of class members. But then I guess since class is (so similar to) struct maybe it's not a capital offence. Are you allowed to do this sort of inspection of class members? I guess there are rules about the compiler must put all member variables first, etc.?


  • Moderators

    @JonB class and struct are the same thing except that by default access is private in class and public in struct. Memory layout wise they're the same (if not plunging into topics like multiple inheritance).

    Are you allowed to do this sort of inspection of class members?

    I've been doing this for years and no police came knocking :)
    Seriously though that's what the offsetof and sizeof are for. They are part of the language. The part that's not guaranteed is the actual value that those return and that will vary between platforms, compilers, optimization levels etc. There are also no requirements for specific vtable implementation etc. so this will differ too, but simple stuff like how many bytes is a member away from the instance address is perfectly fine.



  • @Chris-Kawa
    Yes, thanks, I get it. My initial thought was "you mustn't mess with any class member layouts, they are not guaranteed or defined or useful etc." But then as I wrote i keep being told that in C++ class == struct, so then I know what expectations I can have.



  • @Chris-Kawa class and struct are the same thing except that by default access is private in class and public in struct.
    If I remember it correctly, struct is converted to class public part when it is compiled. Therefore, there is no more reason to use struct in C++ except for C code.


  • Moderators

    @JonB said in Do member `const`s save memory?:

    First, may I say I am well aware of how, say, char * or constexpr would have worked instead. I picked the example I did (silly as it is) precisely because it is not one of those type of constructs,
    Yes, thinking it through I did appreciate about it must be a properly-allocated member of the class in each instance. So I do get why.

    In addition to @Chris-Kawa's comment, const is for you and you alone, it's not a storage specifier. The compiler doesn't and can't optimize anything about it, as you can strip it at any time (mutable members and const_cast come to mind).

    @JonB said in Do member `const`s save memory?:

    Oh, BTW, you said "on the stack", but that's only if my instances are on the stack. If I new them it's occupying space on the heap, surely?

    Yes, it's slang for "auto-storage", where the size is known at compile time (as opposed to direct heap allocations).

    @JoeCFD said in Do member `const`s save memory?:

    If I remember it correctly, struct is converted to class public part when it is compiled. Therefore, there is no more reason to use struct in C++ except for C code.

    struct and class have no meaning when you compile something, so no, nothing is converted into anything. Objects are pieces of memory with a specific data layout, whilst methods go into the static portion (.text section) of the binary. Virtual methods have an additional level of indirection through the virtual table, which is pointed by the vptr contained somewhere in the actual object data (usually the first, hidden, data field).

    PS.

    @Chris-Kawa said in Do member `const`s save memory?:

    If you don't want to modify it use const char* fred = "abc" instead of an array.

    That should be const char * const fred = "abc", otherwise the compiler is going to (rightfully) complain about it.


Log in to reply