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.
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.
[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...
Constructors build objects from dust.
This is a statement which I have been coming across many times,recently.
While initializing a built-in datatype variable, the variable also HAS to be "built from dust" . So, are there also constructors for built in types?
Also, how does the compiler treat a BUILT IN DATATYPE and a USER DEFINED CLASS differently, while creating instances for each?
I mean details regarding constructors, destructors etc.
This query on stack overflow is regarding the same and it has some pretty intresting details , most intresting one being what Bjarne said ... !
Do built-in types have default constructors?
Simply put, according to the C++ standard:
12.1 Constructors [class.ctor]
2. A constructor is used to initialize objects of its class type...
so no, built-in datatypes (assuming you're talking about things like ints and floats) do not have constructors because they are not class types. Class types are are specified as such:
9 Classes [class]
1. A class is a type. Its name becomes a class-name (9.1) within
its scope.
class-name:
identifier
template-id
Class-specifiers and elaborated-type-specifiers (7.1.5.3) are used
to make class-names. An object of a class consists of a (possibly
empty) sequence of members and base class objects.
class-specifier:
class-head { member-specification (opt) }
class-head:
class-key identifieropt base-clauseopt
class-key nested-name-specifier identifier base-clauseopt
class-key nested-name-specifieropt template-id base-clauseopt
class-key:
class
struct
union
And since the built-in types are not declared like that, they cannot be class types.
So how are instances of built-in types created? The general process of bringing built-in and class instances into existance is called initialization, for which there's a huge 8-page section in the C++ standard (8.5) that lays out in excruciating detail about it. Here's some of the rules you can find in section 8.5.
As already mentioned, built-in data types don't have constructors.
But you still can use construction-like initialization syntax, like in int i(3), or int i = int(). As far as I know that was introduced to language to better support generic programming, i.e. to be able to write
template <class T>
T f() { T t = T(); }
f(42);
While initializing a built-in datatype variable, the variable also HAS to be "built from dust" . So, are there also constructors for built in types?
Per request, I am rebuilding my answer from dust.
I'm not particularly fond of that "Constructors build objects from dust" phrase. It is a bit misleading.
An object, be it a primitive type, a pointer, or a instance of a big class, occupies a certain known amount of memory. That memory must somehow be set aside for the object. In some circumstances, that set-aside memory is initialized. That initialization is what constructors do. They do not set aside (or allocate) the memory needed to store the object. That step is performed before the constructor is called.
There are times when a variable does not have to be initialized. For example,
int some_function (int some argument) {
int index;
...
}
Note that index was not assigned a value. On entry to some_function, a chunk of memory is set aside for the variable index. This memory already exists somewhere; it is just set aside, or allocated. Since the memory already exists somewhere, each bit will have some pre-existing value. If a variable is not initialized, it will have an initial value. The initial value of the variable index might be 42, or 1404197501, or something entirely different.
Some languages provide a default initialization in case the programmer did not specify one. (C and C++ do not.) Sometimes there is nothing wrong with not initializing a variable to a known value. The very next statement might be an assignment statement, for example. The upside of providing a default initialization is that failing to initialize variables is a typical programming mistake. The downside is that this initialization has a cost, albeit typically tiny. That tiny cost can be significant when it occurs in a time-critical, multiply-nested loop. Not providing a default initial value fits the C and C++ philosophy of not providing something the programmer did not ask for.
Some variables, even non-class variables, absolutely do need to be given an initial value. For example, there is no way to assign a value to a variable that is of a reference type except in the declaration statement. The same goes for variables that are declared to be constant.
Some classes have hidden data that absolutely do need to be initialized. Some classes have const or reference data members that absolutely do need to be initialized. These classes need to be initialized, or constructed. Not all classes do need to be initialized. A class or structure that doesn't have any virtual functions, doesn't have an explicitly-provided constructor or destructor, and whose member data are all primitive data types, is called plain old data, or POD. POD classes do not need to be constructed.
Bottom line:
An object, whether it is a primitive type or an instance of a very complex class, is not "built from dust". Dust is, after all, very harmful to computers. They are built from bits.
Setting aside, or allocating, memory for some object and initializing that set-aside memory are two different things.
The memory need to store an object is allocated, not created. The memory already exists. Because that memory already exists, the bits that comprise the object will have some pre-existing values. You should of course never rely on those preexisting values, but they are there.
The reason for initializing variables, or data members, is to give them a reliable, known value. Sometimes that initialization is just a waste of CPU time. If you didn't ask the compiler to provide such a value, C and C++ assume the omission is intentional.
The constructor for some object does not allocate the memory needed to store the object itself. That step has already been done by the time the constructor is called. What a constructor does do is to initialize that already allocated memory.
The initial response:
A variable of a primitive type does not have to be "built from dust". The memory to store the variable needs to be allocated, but the variable can be left uninitialized. A constructor does not build the object from dust. A constructor does not allocate the memory needed to store the to-be constructed object. That memory has already been allocated by the time the constructor is called. (A constructor might initialize some pointer data member to memory allocated by the constructor, but the bits occupied by that pointer must already exist.)
Some objects such as primitive types and POD classes do not necessarily need to be initialized. Declare a non-static primitive type variable without an initial value and that variable will be uninitialized. The same goes for POD classes. Suppose you know you are going to assign a value to some variable before the value of the variable is accessed. Do you need to provide an initial value? No.
Some languages do give an initial value to every variable. C and C++ do not. If you didn't ask for an initial value, C and C++ are not going to force an initial value on the variable. That initialization has a cost, typically tiny, but it exists.
Built In data types(fundamental types, arrays,references, pointers, and enums) do not have constructors.
A constructor is a member function. A member function can only be defined for a class type
C++03 9.3/1:
"Functions declared in the definition of a class, excluding those declared with a friend specifier, are called member functions of that class".
Many a times usage of an POD type in certain syntax's(given below) might give an impression that they are constructed using constructors or copy constructors but it just Initialization without any of the two.
int x(5);
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.