Why does this C++ data member declaration contain an ampersand? [duplicate] - c++

This question already has answers here:
how does the ampersand(&) sign work in c++? [duplicate]
(3 answers)
What does '&' do in a C++ declaration?
(7 answers)
What are the differences between a pointer variable and a reference variable?
(44 answers)
Closed 2 years ago.
I am a novice trying to understand some C++ code in the open-source game Simutrans. Specifically, this declaration (line 79 in this header file):
class env_t
{
public:
<snip>
/// if we are the server, we are at this port
/// #see network_init_server()
static const uint16 &server;
The context tells us this line concerns public data members of the class env_t. The static keyword tells us that all objects of class env_t will have the property server.
Server's type is uint16 (a 16-bit unsigned integer) and it is a constant (so it cannot be overwritten in normal circumstances).
The part that puzzles me is why there is an ampersand (&) at the beginning of the member's name. I have only previously come across the ampersand in bitwise arithmetic and as the "address of" operator. Neither of those uses fit here: there is no arithmetic and I do not see how you could define server as the address of server. Wouldn't that be telling the program that the only possible value of the variable is the variable's own memory address? That not only seems to be circular, but it seems to be inconsistent with the fact that the program can definitely use more than 16 bits of memory addresses for other purposes.
It has been difficult to search for explanations because the ampersand is also a search operator. But this article gives seven different uses of ampersands in C++ and none of them seem to fit here. It's not an expression nor a double ampersand. According to these S.O. answers, the ampersand can be used in a function template to indicate that a parameter must be of a reference type. But my example is declaring a data member, which is not a template, and indeed not any kind of function. And the type is clearly uint16, right? So what does the ampersand indicate here, please?
It should be noted that Simutrans is more than two decades old, before all platforms had the Standard Library, so its code is sometimes idiosyncratic. But I am sure the more relevant fact is that I'm a beginner at C++!

That notation indicates that server is a reference. This has enough similarities to pointers that if you are comfortable with them, you can think of them as a very restricted pointer. If you aren't so comfortable with pointers, a reference is not a variable that holds onto its own data. Rather, it is a reference to another variable. This notation indicates that server is actually referring to data somewhere else, most likely outside of your env_t class.
This is typically done for two reasons. One is that if you change this value, it changes the value of the actual variable being referred to, so that if another piece of code looks at its value, they'll see your change. Vice versa, if someone else changes the value of the variable referenced by server, and you query the value of server, you'll see their changes.

Related

C++ - Incomplete class type? [duplicate]

This question already has answers here:
"Incomplete type" in class which has a member of the same type of the class itself
(8 answers)
Closed 6 years ago.
I've been working with a lot of C and Java lately so I'm a bit confused coming back to C++ on why this is not allowed.
incomplete type is not allowed
#pragma once
class Expression
{
private:
Expression power; // <--- incomplete type is not allowed
};
I believe the answer here is to change the line Expression power to Expression *power but I don't understand why that is. I can declare objects like vector<int> var without having to make them a pointer, but the second I have an object of the same type as the file it's being declared in, I need one? I've looked around but cannot find any tutorials/videos on a class making an object of itself.
If you put an instance of a class inside itself, if you notice, you are creating recursion, since every instance has its own Expression power, and this goes on forever. If you have a pointer though, you can control this infinite recursion, since at any time you can set power to nullptr, (or NULL/0, pre C++11), to end the recursion.

Can I pass this through a function?

I'm wrapping a scripting library and this macro exists.
#define asOFFSET(s,m) ((size_t)(&reinterpret_cast<s*>(100000)->m)-100000)
what type is m? It has the example:
struct MyStruct
{
int a;
};
asOFFSET(MyStruct,a)
I want to put this into a function.
The macro is (most likely) used by the scripting library to find out the internal layout of a class's members without making assumptions about its type, architecture or inheritance model.
(A simple example is discussed here).
For most C++ programs, this information (memory layout) should ideally not be needed at all. But in the off chance that you do need it (e.g. if you're writing an analyser / debugger), you would be better off retaining this macro as-is (or preferably replacing its usage in your code with offsetof as Michael Anderson points out.) There are compiler-specific implementations which are
more efficient
less likely to be reported as performing an invalid operation (e.g. dereferencing an invalid memory address when using tools like Valgrind).
With these equivalent options, a hand-spun alternative or wrapper should ideally not be needed.
This is an implementation of the offsetof macro. m is any member of s. It doesn't have a corresponding C or C++ type - but is closely related to the concept of pointer to member.
The purpose of the macro is to determine, given any name of a struct and any name of a member of that struct, the distance in memory from the beginning of an arbitrary instance of the struct, and the location of that member in the same instance.
m does not have a "type", and neither does s. The entire concept of "type" goes out the window when you use macros. This stuff simply is not C++; it's basically a completely separate language that's used to edit C++ code in-place. When the preprocessor runs, asOFFSET(MyStruct, a) will be literally replaced with the text ((size_t)(&reinterpret_cast<MyStruct*>(100000)->a)-100000) before the compiler even begins its work.
((size_t)(&reinterpret_cast<MyStruct*>(100000)->a)-100000) is intended to evaluate to 0, because the a member of MyStruct instances appears at the beginning of each instance. I'm not actually 100% sure that this is legal behaviour per the specification, but the intent is as follows:
Pretend that there is an instance of MyStruct at the memory location 100000, by treating the number 100000 as if it were a pointer to a MyStruct.
Get the address in memory of the a member of this fake struct, and subtract 100000 again. That gives us the distance from the beginning of the fake struct to the specified member of that fake struct.
Cast that numeric value back to size_t (the numeric type used for measuring memory allocations, an unsigned integer type).

what is the "&" behind variables in C++ templates? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
What does “Class* &cls” mean in C++'s function definition?
i came across this code:
template <class T,class U> void inline TIntDataSwap2(U data,T i)
{
unsigned char*& data2=(unsigned char*&)data;
data2[0]=(unsigned char)(((unsigned int)i>> 8)&0xff);
data2[1]=(unsigned char)(((unsigned int)i>> 0)&0xff);
};
what is the meaning of the "&" behind "unsigned char *"?
can this only be used in templates? i have never seen it before and "& behind a variable" is hard to google up, please help me...
Reference operator - MSDN source.
The & is not "behind a variable" but part of the type.
You are probably already aware of what a reference is in C++. In this case, unsigned char *& is just a reference to a pointer to unsigned char.
This is completely independent of templates, and can be used inside or outside a template definition,
unsigned char*& is a reference to a pointer to a unsigned char. Always read the pointer/reference combination from right to left. This is in no way restricted to use within templates.
Normally when you pass an argument to a function, it is passed by value in C++ (even huge objects). A copy is made, which is what is passed to the function. This both consumes additional memory and prevents the function from modifying the argument you pass to it (since it only gets a copy). Using a reference, we don't make a copy so it is more memory efficient. It also allows the function to modify the argument if needed. If you only want the performance gain and don't want the function to modify the argument, you can declare the parameter a const reference.

What is the benefit of the const keyword in programming? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Sell me on using const correctness
I'm eager to know the answer. [to "What is the benefit of const keyword in programming?"]
const indicates that the value assigned to the variable cannot change. If you try to change the value you should get a compiler error.
The const keyword can declare a read only variable.
Using const parameters to a method tells you the method will not change the parameter.
A const method tells you that the method will not alter a class's member variables (but can change member variables marked as mutable)
You can also declare const pointers, better described here
What is the benefit of const keyword in programming?
Specifying a variable as const states that the variable's value should never change after the initial assignment. This allows the compiler to perform additional tests at compilation (validating your code).
For example, if a const function changes a (non-mutable) member in an object, the compiler will yield an error.
Benefit: You get more compile time checks to ensure that you're not changing data that shouldn't be changed.
Cost: You have to use it everywhere. If you need to, you can cast your way out of it, nullifying the benefits.
Getting usage right can be tricky with pointers. Is the pointer itself const, or the data it refers to? This is also the most common usage I've seen: you want to point to immutable memory.

Why was the ampersand chosen as the symbol for references in C++? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
Does anyone have an idea why the ampersand was chosen as the way to denote references in C++?
AFAIK (though I don't have the book near me), Stroustroup didn't explain that choice, which I find a little odd because the same symbol was already used for address-of in C.
In addition to Earwicker's response which I generally agree with. I would also speculate that since & is the "address-of" operator, it is somewhat fitting. Since a reference in many ways is like passing by address instead of by value.
In addition to that, taking the address of a variable is often referred to as "referencing"
(Yes I know that references don't have to be implemented using pointers under the hood, I am referring to the way they conceptually work).
This is just speculation though.
Stroustrup was always very reluctant to introduce a new reserved symbol or name, so he probably used it to avoid making the feature look weird to users of C.
Who knows why Stroustrup does anything, but my guess is that because the implementation of reference parameters involves passing the address of an lvalue, Stroustrup chose the C address-of operator because it would give C programmers the right idea about the cost model.
Here is my theory on that. I think it has much to do with what operators are valid (syntactically) for symbols. Consider
int a[1]; // a[1] is valid (syntactically)
int *a; // *a is valid
int a(char, bool); // a(<a char>, <a bool>) is valid (function call)
int C::*a; // <a C>.*a is valid
Conceptually, in those declarations what is named with a type (C, char, bool) is substituted with an expression of that type later on. Of course the intention is to reuse as much of the existing language as possible. So i think he used &:
int &a; // &a is valid
The important one is that & is only valid on the kind of expression a reference denotes: For lvalues. References are lvalues (named variables are too) and only for them & can be applied:
int &g(); // &g() is valid (taking the address of the referred to integer)
int g(); // &g() is *not* valid (can't apply to temporary int)
My thought was that there are 2 symbols used in pointers: * and &.
since int* means a pointer to an int, probably Stroustrup didn't want to introduce a whole new symbol. Since references are sort of like pointers, he stuck with &. Plus, the only previously valid use of & was to take the address of something, so it was OK to use in declarations.