[basic] p6 states:
A variable is introduced by the declaration of a reference other than a non-static data member or of an object. The variable's name, if any, denotes the reference or object.
int a = 0; // declaration of an object, this introduces the variable x, and an object is created
int{0}; // not a declaration of a variable, this does not introduce a variable, but an object is created
Does this mean that a variable IS an object or reference (that is not a non-static member)? Throughout the standard, they are referred to as if they have the properties of objects/reference, but the formal definition does not seem to state that. What confuses me is that the variables name refers to the object or reference, rather than the variable itself.
For example, here is what [basic.life] p1 has to say:
A variable is said to have vacuous initialization if it is default-initialized and [...]
This alludes to variables having the same properties as objects and references, as they can be initialized.
So my question is:
Are variables simply a syntactic construct meant to group object and references that have been introduced by a declaration into one term? Is the variable itself the object or reference?
As made clear in Basic/3, variables are not "entities". Objects and references are entities, but not variables. As such, you could consider variables to be purely syntactic constructs rather than first-class C++ things.
Basic/6 tells us that a variable name denotes the object/reference declared by that variable. This is supposed to be read as plain English: an object/reference created via a variable declaration has a variable name. And conversely, a variable names an object/reference created via a variable declaration.
So when the standard says:
A variable is said to have vacuous initialization if it is default-initialized and...
It means:
A [reference/object introduced by a variable declaration] is said to have vacuous initialization if it is default-initialized and...
Related
I am learning C++ using the books listed here. My question is that is there a difference between a variable and an object. Consider the following example:
int i = 0; //i is an object of type int. Or we can say i is a variable of type int
int &refI = i; //refI is a "reference variable" of "reference type `int&`. But here refI is not an object.
My current understanding is that both of the terms variable and object overlaps to a large extent. But in some contexts like in case of refI above, there can be some differences. In particular, refI is a reference variable of reference type int& and refI is not an object because a reference is an alias for some other object. While i is both an object and a variable.
My question is that am i correctly analyzing the refI case above? If not, what does the standard say about this.
My second question is that, does the standard C++ strictly differentiate between these two terms. If yes, how and where. For example something like,
a variable may be defined as an object with a name. And any object without a name is not a variable.
Here the user says that a variable and object are different.
Edit
I am also asking this question because i am aware that in Python(as it is a dynamically typed language) there is a clear distinction between variables and objects. Does the C++ standard also make such a clear distinction.
Difference between an object and a variable in C++
Variable is a programming language level concept. A variable has a type and it (usually) has a name. A variable can denote an object, or a reference.
There's no concise definition for the meaning of "variable" in the standard nor a section dedicated to them alone, but closest individual rule to specifying its meaning is:
[basic.pre]
A variable is introduced by the declaration of a reference other than a non-static data member or of an object.
The variable's name, if any, denotes the reference or object.
Object is a concept in the level of the abstract machine that the language defines. It is mostly specified in the section "Object model [intro.object]" which begins:
[intro.object]
The constructs in a C++ program create, destroy, refer to, access, and manipulate objects.
An object is created by a definition, by a new-expression ([expr.new]), by an operation that implicitly creates objects (see below), when implicitly changing the active member of a union, or when a temporary object is created ([conv.rval], [class.temporary]).
An object occupies a region of storage in its period of construction ([class.cdtor]), throughout its lifetime, and in its period of destruction ([class.cdtor]).
int i = 0; //i is an object of type int. Or we can say i is a variable of type int
i is a variable of type int. The variable's name denotes an object.
int &refI = i; //refI is a "reference variable" of "reference type `int&`. But here refI is not an object.
refI is a variable of type int&. The variable's name denotes a reference. The reference is bound to the object named by i and can be seen as another name for the same object.
Your understanding seems to be correct. I'm going to reuse the quote from #RichardCritten answer, but with a different explanation.
[basic.pre]/6
A variable is introduced by the declaration of a reference other than a non-static data member or of an object.
The variable's name, if any, denotes the reference or object.
So a variable is one of:
A named object, e.g. int i = 1;. Non-static data members don't count. Functions don't count, since they're not objects, see below. Named objects are always created by declarations.
An unnamed object that has a declaration. The only ones I'm aware of are unnamed function parameters (and structured bindings, see below).
A named reference, e.g. int &j = i;. Non-static data members don't count. Named references are always created by declarations.
An unnamed reference that has a declaration. The only ones I'm aware of are unnamed function parameters (and structured bindings, see below). As far as I'm aware, there are no unnamed references without declarations, since expressions can't have reference types.
A structured binding: there's a single unnamed object or reference per structured binding (regardless of the number of identifiers), AND, if this structured binding was initialized with a std::tuple-like class (as opposed to an array or a class with magically detected members), there's also one reference per each member (unnamed, surprisingly - the identifiers magically refer to those references, they are not their names).
[intro.object]
The constructs in a C++ program create, destroy, refer to, access, and manipulate objects. An object is created by a definition, by a new-expression, by an operation that implicitly creates objects (see below), when implicitly changing the active member of a union, or when a temporary object is created. An object occupies a region of storage in its period of construction, throughout its lifetime, and in its period of destruction.
[Note 1: A function is not an object, regardless of whether or not it occupies storage in the way that objects do.
— end note]
The properties of an object are determined when the object is created. An object can have a name. An object has a storage duration which influences its lifetime. An object has a type.
The above explains what counts as an object.
But I find it easier to remember what isn't one:
Functions are not objects. (see quote above)
References are not objects. (again, note that expressions can't have reference types; there are no temporary unnamed references)
Prvalues are not objects (since C++17).
If the "object" doesn't exist, it isn't an object (i.e. if its lifetime hasn't started or has already ended, AND its constructor nor destructor are currently running).
Obviously, labels are not objects, and neither are macros.
Ignoring the language-lawyer tag since you are just learning. You don't need to know the exact wording of the standard to be able to understand the example you gave.
int i = 0; //i is an object of type int. Or we can say i is a variable of type int
int &refI = i; //refI is a "reference variable" of "reference type `int&`. But here refI is not an object.
Both i and refI are variables. Anything you give a name is a variable.
But both i and refI are also objects. Every variable has an address in memory where it lives and that makes it an object. There are objects that are not variables, for example the C string literal "Hello, world!". The string is placed somewhere in memory and has an address, it is an object. But it has no name so it isn't a variable.
Note: If nothing uses the address of an object the compiler may, and often will, optimize. Often the data is only kept in CPU registers and never actually stored in memory.
So to summarize: All variables are objects but not all objects are variables.
Current Draft Standard basic.pre.6 "A variable is introduced by the declaration of a reference other than a non-static data member or of an object. The variable's name, if any, denotes the reference or object."
The standard says
A variable is introduced by the declaration of an object. The variable's name denotes the object.
But what does this definition actually mean?
Does a variable give a name to an object, i.e. are variables just a naming mechanism for otherwise anonymous objects? Or is a variable the name itself?
Or is a variable a named object in the sense that every variable is also an object?
Or is a variable just a "proxy" with a name that "delegates" all operations to the real object?
To confuse things further, many C++ books seem to treat variables and objects as synonyms.
What is your take on this?
About entities, quoting from the C++0x draft:
An entity is a value, object, reference, function [...]
Every name that denotes an entity is introduced by a declaration.
A variable is introduced by the declaration of an object
From these statements I draw the conclusion that a variable is a name and thus cannot be an object. This is really confusing the hell out of me :)
Variables are named objects. The following create objects that are not variables
new int // create one int object
std::string() // create one string object
The following creates one array variable with name "foo" and 5 unnamed (sub-) objects of type "int"
int foo[5];
The following is not a variable in C++03, but has become a variable in C++0x (declared references are variables in C++0x, for details see the link)
extern int &r;
Does a variable give a name to an object, i.e. are variables just a naming mechanism for otherwise anonymous objects?
Variables are objects (or references respectively). The entity list (3/3 in C++03) of C++ contains multiple such is-a relationships. For instance, a sub-object is-a object and an array element is-a object and a class-member is-a object or function or type or template or enumerator.
The entity list of C++0x looks a bit cleaner to me, and it doesn't contain "variables", "instance of a function" (what that kind of entity even is has never been apparent to me), "sub-object" and "array element" anymore. Instead it added "template specialization" which either are functions, classes or templates (partial specializations).
The C++ object model at 1.8 says
An object can have a name (clause 3).
So if you like, you can formulate the statement as "The object's name denotes the object.".
Variables are names that you give to objects, so yes, objects are, by and large, anonymous.
Here's the definition from the C++17 standard:
A variable is introduced by the declaration of a reference other
than a non-static data member or of an object. The variable’s name, if
any, denotes the reference or object.
My take on this, quite frankly, is that that's not really a definition. It tells us what introduces a variable, but it doesn't define what a variable is.
Consider, for example:
int foo = 42;
This is a declaration of an object, so it "introduces" a variable. But what is the variable? Is the object named foo a variable? I would have thought so, but the definition doesn't actually say that. Apparently the "variable" has a name (in this case "foo") and that name denotes the object. Since it has a name, presumably the name itself is not the variable. And it would have been easy enough to say that the variable is the object, rather than that the variable's name denotes the object, if that were the intent.
What is a "variable" in C++? I really don't know, and I don't believe it's possible to answer the question based on the wording in the standard. (And I'd like that to be corrected in a future edition.)
(The C standard deals with this by not defining "variable" and, for the most part, not using it except as an adjective or informally.)
A variable is simply an entity with a type and a name
As I have learned
What are variables
A variable is an identifier that is bind to a value stored in the system's memory(imperative languages) or an expression that can be evaluated(functional languages).
Why we need variables
provide names for storage chunks to store data temporarily during the lifespan of a computer program.
are also used in programming to transfer information from one part of the program to another part(Eg: parameters, global variables).
A variable is really a name given to an object in memory and hence an object is an anonymous type in that respect just at the point before compilation, when the compilation occurs, the variable is kept track of during the syntactical and parsing phase, then when the linker kicks in, that variable will have a memory address assigned to it, although at run-time, that memory address will be correctly off-setted somewhere to take into account of dynamic linking or static linking. Hence the variable can then be easily referenced aka the memory address that the variable is assigned to.
Really, in a nutshell, the variable is to help the programmer to work out the junction points of execution where that variable is referenced in terms of machine code.
What is your take on this?
Variable is a block of memory on stack or in code segment, or a value in a register (if the size of variable is small enough, although normally it is still value in a memory while registers hold temporary results), with name provided for programmer's convenience. Name of variable does not exist after compilation (we're not talking about macro tricks here). Any access to the variable is resolved into memory access, so technically variable is an address of corresponding data block, and that address isn't stored anywhere. Think about declaration of variables in assembly languages - variable "kinda" exists, but it is still merely an offset to the data block.
I think that this definition is quite clear.
The variable is introduced by declaration and denotes the object. Who introduces the variable? You do of course, and thus it is you who uses it.
A variable is really only a convenience for you the developer. It is a fundamental aspect of most programming languages not just C++. A variable mearly gives a symbolic name to a useable entity that occupies storage, such that it can be referenced and used at a future point in your source code.
For example if you declare a variable in a method as such:
int x = 5;
This will be reduced by the compiler to some offset from the stack pointer, say SP + 0x003.
At some point later you can say:
x = 52;
In this case the area of stack memory SP + 0x003 will contain the bytes that describe the number 52.
You declare the variable to be of a certain type so that the compiler can work out how much space the data occupies in memory.
Without variables, you would have to manage all of the arrangement of information yourself and you would probably be coding in assembly or lower.
Variable is a name for the object. You access the object through this named entity.
As the title suggests, this question has been asked before. However, the answers pertained to C++03/0x(11). C++11 (N3337) says this about variables:
[basic]/6:
A variable is introduced by the declaration of a reference other than a non-static data member or of an object. The variable’s name denotes the reference or object.
This may imply that variables are essentially named objects/references.
However, in C++14/C++17, that last sentence was changed to
The variable’s name, if any, denotes the reference or object.
which implies that a variable does not necessarily have a name.
A different interpretation of the first sentence may suggest that a variable is a name, since a name denoting an object/reference is also introduced by a declaration of such entities. But the second sentence contradicts that notion with the phrase "variable's name". So, is variable now just a hypernym for object and reference, whether named or not?
This change was a result of CWG 1769, addressing the status of exception objects bound to unnamed catch handler parameters:
catch (std::exception&) // <==
{
}
That is now a variable. This simplifies the conceptual model around exception objects.
The first sentence, which remained unchanged, is still the complete definition of the term variable.
I want to reshoot a question based on the answer and appending discussion of:
Why is a non static data member reference not a variable?:
A non-static data member of class doesn't create a new variable itself, it just helps you to define the properties of the class. If it did create a new variable, you'd be able to write code like this:
class Chamber {
public:
int pot;
};
void f(bool b) {
if (b)
Chamber::pot = 2;
}
What would that even mean? Would it find every instance of Chamber and set all their pots to 2? It's a nonsense.
However, in the current n4296 c++17 draft a variable is still definened as (§3.6):
A variable is introduced by the declaration of a reference other than a non-static data member or of an
object. The variable’s name, if any, denotes the reference or object.
The argumentation in the accepted answer seems logical to me but it is, based on my understanding of the variable-definition above, conflicting with the standard.
Question Are non-static non-reference data member declarations variables, and if yes, why are they considered to be so since I cannot use them in an intuitive fashion ( as e.g. Chamber::pot from the example in the answer ) ?
No, as Igor Tandetnik pointed out in the comments, non-static data member declarations are never variables, because they are never objects. They are declarations that give the member an object type, but there are no objects until an instance of the class is created.
Quoting Richard Smith:
I suppose the problem is in the ambiguity of what a "declaration of a reference" is. I believe the intent here is that a "declaration of a reference" is a declaration that declares a particular name to be of reference type (which a non-static data member declaration of reference type does), not necessarily a declaration that causes the lifetime of a particular reference to begin. Conversely, a "declaration of an object" is intended to be interpreted as a declaration that declares a particular name to name a specific object (which a non-static data member declaration does not).
That is:
struct A {
int &a;
int b;
};
'a' is a declaration of a reference, and so we need another condition to restrict it from being a variable. 'b' is /not/ a declaration of an object, so we don't need to say anything further.
Suggestions on how to reword this to make it clearer would be welcome :)
This was followed up as https://github.com/cplusplus/draft/issues/1280, some inconsistencies were found. With some luck, this will be seen as a good opportunity to clear up the standard at the same time.
The argumentation in the accepted answer seems logical to me but it is, based on my understanding of the variable-definition above, conflicting with the standard.
There is no conflict with the standard, you've misunderstood the text you quote from §3.6.
A non-static data member is not an object, so it's not a variable either.
An object occupies a region of storage for the duration of its lifetime (see [intro.object]). A non-static data member declaration does not begin the lifetime of some thing that occupies a region of storage. So it doesn't create an object.
When you construct an object of the class' type there will be a sub-object corresponding to the data member, but that subobject is created when the enclosing object is created, and only exists for the object's lifetime. It is not created by the declaration of the data member in the class.
i.e. a subobject for the data member is created when the class object that contains it is created, not when the data member is declared.
So if it's not an object, then it's not a variable.
Question Are non-static non-reference data member declarations variables,
No.
n3035 says:
A variable is introduced by the declaration of an object. The variable's name denotes the object.
n3090 says:
A variable is introduced by the declaration of a reference other than a non-static data member or of an object. The variable's name denotes the reference or object.
I wonder what motivated this change. Does it have to do with rvalue references?
The change was in response to CWG defect 633. The list of changes related to this can be found in n2993:
The goal of these changes is to expand the meaning of "variable" to encompass both named objects and references, and to apply the term consistently wherever feasible.