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? -
@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)
-
@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). -
@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.
-
@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 -
@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.
-
@JonB wrap it in a constexpr getter :D
-
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 saychar*
and start iterating up to thesizeof
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 *
orconstexpr
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 memoryI 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 ofclass
members? I guess there are rules about the compiler must put all member variables first, etc.? -
@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 anyclass
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. -
@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 andconst_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
andclass
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 thevptr
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.