0

In C# const implies static so you can reference a public const without having to reference an instance of a class or struct. In C++ this is not the case. If you want to access a const member variable in C++ you need to first have a reference to an instance of the class. In C++ as far as I can tell making a member variable const causes its data to be either replaced with an literal value or stored in the text or data segment (depending on the compiler) of the program. So my question is, if const member variables are allocated only once for a given class (not per instance) and stored in an area separate from instance specific member data, why can't you access a public const class member variable without a reference to an instance of the class such as:

struct Example {
   const int array[] = {1, 2, 3};
};

void main() {
   std::cout << Example::array[1];
}

Instead you need to make them a static const and initialize them outside of the class such as:

struct Example {
   static const int array[3];
};

const int Example::array[3] = {1, 2, 3}

void main() {
   std::cout << Example::array[1];
}
Ryoku
  • 397
  • 2
  • 16
  • 2
    "if const member variables are allocated only once for a given class" What makes you think that it works like that? – Support Ukraine Dec 09 '20 at 11:54
  • A non-static `const` data member of a class can have a different value in different instances of that class. The `const` simply means that once initialized it can't be modified. – G.M. Dec 09 '20 at 11:57
  • @G.M. Thank you for the clarification, I wasn't aware that const variables could vary per instance as [this stack overflow question](https://stackoverflow.com/questions/14588767/where-in-memory-are-my-variables-stored-in-c/14588866) lead me to believe. I would assume that this also means that in those cases they are actually stored on the stack or heap with the rest of the per instance data and not in the data or text sections. – Ryoku Dec 09 '20 at 12:06
  • There may be only one (i.e. per-class) instance of a `const` class member in C#. C++ has one instance of a `const` member per instance of the class (and that member can be initialised by a constructor when initialising the containing object). Members of a class are not usually `static` unless specifically declared as `static`. More generally questions of the form " does it this way and why does C++ do it differently?" have a general answer "Because C++ and are different languages that are designed to meet different purposes". – Peter Dec 09 '20 at 12:22
  • @Ryoku Note that the question you linked is about _C_, not C++. C doesn't have classes at all, so drawing conclusions about how C++ stores information about class member variables from how C does anything is hazardous. – Nathan Pierson Dec 09 '20 at 15:16

1 Answers1

3

Just because the member is const does not imply that it has the same value in all instances. Consider:

 struct foo {
     const int x = 1;
     foo(int a) : x(a) {}
 };

 foo a{1};
 foo b{2};

Now a and b have different values for their const int member. I don't know C# but it looks like something is missing when you cannot have const non-static members. On the other hand const members come with some downsides in C++ and the easiest is to avoid them completely in favor of encapsulation (when there is no setter and the member is never modified within the class, it is essentially constant).

Note that even though there is a default initializer for the member = 1; this does not imply that all instances have the same value for x. Default initializers only apply when a constructor does not provide an initializer in its member initialization list, but in the above example it does so.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • Thanks for the clarification. I still find it strange that if you set `const int x = 1` you can't access the member variable without an instance reference despite it being constant for every instance of the class, but at least I can see why in the general case its not applicable. – Ryoku Dec 09 '20 at 12:09
  • 1
    @Ryoku I suppose you refer to the default initializer. See edit. It doesnt change the fact that different instances can have different values for `x` – 463035818_is_not_an_ai Dec 09 '20 at 12:12
  • @Ryoku • *I still find it strange...* If you want to have a class variable rather than an instance variable, use the `static`. This should not be "strange" in C++, it's been part of the language for a very long time. – Eljay Dec 09 '20 at 12:16
  • @largest_prime_is_463035818 your right I was and that's a perfect explanation thank you. I had no idea that it was merely a default initializer for if no other was provided. – Ryoku Dec 09 '20 at 12:17
  • @Ryoku also note that `static` is one of the C++ keywords that can have very different meanings. Though, from your example it is clear what you mean. – 463035818_is_not_an_ai Dec 09 '20 at 12:17
  • @largest_prime_is_463035818 thanks for the advice, I'll familiarize myself more with the static keyword to make sure I'm not using it incorrectly. – Ryoku Dec 09 '20 at 12:19
  • @Ryoku • [`static`](https://en.cppreference.com/w/cpp/keyword/static) may be helpful. It covers the different contextual meanings of `static`. (C++ reused some keywords rather than create yet another keyword, which may collide with existing code.) – Eljay Dec 09 '20 at 13:16
  • @Eljay Thanks for the reference. I've never even considered using `static` outside of a class until I began reading your reference. Still not sure if I will use it, but its interesting to see how its handled. – Ryoku Dec 09 '20 at 13:27