Why references to the same constant take distinct memory space in C++?
up vote
3
down vote
favorite
I'm new to the idea of reference in C++, I have a question concerning the memory allocation of reference to a pure number constant. (Another thing I want to check first is that I suspect const reference, which I frequently came across, means reference to const, but I'm not sure.)
Here is my testing on ideone.com:
#include <stdio.h>
int main() {
const int r0 = 123;
const int &r1 = 123;
const int &r2 = 123;
const int &r3 = r2;
printf("%pn", (void *)&r0);
printf("%pn", (void *)&r1);
printf("%pn", (void *)&r2);
printf("%pn", (void *)&r3);
return 0;
}
and the result:
0x7ffee3bd74c4
0x7ffee3bd74c8
0x7ffee3bd74cc
0x7ffee3bd74cc
The reason r2
is the same as r3
is clear from this answer - How does a C++ reference look, memory-wise?, which says it's depending on compiler. But I'm thinking about why compiler doesn't also make r0
,r1
,r2
all the same, since all have the same pure constant value 123
. (or called prvalue if no wrong search)
As a note: After some search on this site, I found a most related question - but in python. Although different language but I thought the idea should be the same/similar: from the link, if my program were written in python then there will be only one 123
is in the memory space for saving space.
Some other answers I've read:
C++ do references occupy memory: This answer suggests that if it's necessary thenint &x
is implemented as*(pointer_to_x)
.
How does a C++ reference look, memory-wise?: This answer suggests that compiler will try its best to save space.
c++ reference
add a comment |
up vote
3
down vote
favorite
I'm new to the idea of reference in C++, I have a question concerning the memory allocation of reference to a pure number constant. (Another thing I want to check first is that I suspect const reference, which I frequently came across, means reference to const, but I'm not sure.)
Here is my testing on ideone.com:
#include <stdio.h>
int main() {
const int r0 = 123;
const int &r1 = 123;
const int &r2 = 123;
const int &r3 = r2;
printf("%pn", (void *)&r0);
printf("%pn", (void *)&r1);
printf("%pn", (void *)&r2);
printf("%pn", (void *)&r3);
return 0;
}
and the result:
0x7ffee3bd74c4
0x7ffee3bd74c8
0x7ffee3bd74cc
0x7ffee3bd74cc
The reason r2
is the same as r3
is clear from this answer - How does a C++ reference look, memory-wise?, which says it's depending on compiler. But I'm thinking about why compiler doesn't also make r0
,r1
,r2
all the same, since all have the same pure constant value 123
. (or called prvalue if no wrong search)
As a note: After some search on this site, I found a most related question - but in python. Although different language but I thought the idea should be the same/similar: from the link, if my program were written in python then there will be only one 123
is in the memory space for saving space.
Some other answers I've read:
C++ do references occupy memory: This answer suggests that if it's necessary thenint &x
is implemented as*(pointer_to_x)
.
How does a C++ reference look, memory-wise?: This answer suggests that compiler will try its best to save space.
c++ reference
I suspect the answer is because you ran the code without turning on any optimizations.
– Mooing Duck
Nov 22 at 0:05
@MooingDuck: I was (re-)thinking about whether C++ would do the optimization as python before I fell asleep, then now I just wake up and realize that it should be either the converse/reverse question or C++ should handle it better. What's the canonical way/mechanism when C++ doing this?
– ptr_user7813604
Nov 22 at 3:57
1
By default, compilers generate unoptimized builds, which make it far easier to step through and debug. However, every compiler also has a flag you can pass telling it to build an optimized build, which will shrink it down and make it fast and small. How are you compiling your code?
– Mooing Duck
Nov 22 at 6:05
@MooingDuck: I just clicked run on ideone.com, I did try to find so called optimization options there but it seems like they don't have one. I haven't learned much about optimization since I rarely thinking about optimization.
– ptr_user7813604
Nov 22 at 6:11
1
ptr_user7813604 coliru.stacked-crooked.com lets you pass -O0 through -O3 flags to the compiler, letting you see various results. (-O0 is the default of no optimization, -O3 is the maximum optimizations)
– Mooing Duck
Nov 22 at 7:14
add a comment |
up vote
3
down vote
favorite
up vote
3
down vote
favorite
I'm new to the idea of reference in C++, I have a question concerning the memory allocation of reference to a pure number constant. (Another thing I want to check first is that I suspect const reference, which I frequently came across, means reference to const, but I'm not sure.)
Here is my testing on ideone.com:
#include <stdio.h>
int main() {
const int r0 = 123;
const int &r1 = 123;
const int &r2 = 123;
const int &r3 = r2;
printf("%pn", (void *)&r0);
printf("%pn", (void *)&r1);
printf("%pn", (void *)&r2);
printf("%pn", (void *)&r3);
return 0;
}
and the result:
0x7ffee3bd74c4
0x7ffee3bd74c8
0x7ffee3bd74cc
0x7ffee3bd74cc
The reason r2
is the same as r3
is clear from this answer - How does a C++ reference look, memory-wise?, which says it's depending on compiler. But I'm thinking about why compiler doesn't also make r0
,r1
,r2
all the same, since all have the same pure constant value 123
. (or called prvalue if no wrong search)
As a note: After some search on this site, I found a most related question - but in python. Although different language but I thought the idea should be the same/similar: from the link, if my program were written in python then there will be only one 123
is in the memory space for saving space.
Some other answers I've read:
C++ do references occupy memory: This answer suggests that if it's necessary thenint &x
is implemented as*(pointer_to_x)
.
How does a C++ reference look, memory-wise?: This answer suggests that compiler will try its best to save space.
c++ reference
I'm new to the idea of reference in C++, I have a question concerning the memory allocation of reference to a pure number constant. (Another thing I want to check first is that I suspect const reference, which I frequently came across, means reference to const, but I'm not sure.)
Here is my testing on ideone.com:
#include <stdio.h>
int main() {
const int r0 = 123;
const int &r1 = 123;
const int &r2 = 123;
const int &r3 = r2;
printf("%pn", (void *)&r0);
printf("%pn", (void *)&r1);
printf("%pn", (void *)&r2);
printf("%pn", (void *)&r3);
return 0;
}
and the result:
0x7ffee3bd74c4
0x7ffee3bd74c8
0x7ffee3bd74cc
0x7ffee3bd74cc
The reason r2
is the same as r3
is clear from this answer - How does a C++ reference look, memory-wise?, which says it's depending on compiler. But I'm thinking about why compiler doesn't also make r0
,r1
,r2
all the same, since all have the same pure constant value 123
. (or called prvalue if no wrong search)
As a note: After some search on this site, I found a most related question - but in python. Although different language but I thought the idea should be the same/similar: from the link, if my program were written in python then there will be only one 123
is in the memory space for saving space.
Some other answers I've read:
C++ do references occupy memory: This answer suggests that if it's necessary thenint &x
is implemented as*(pointer_to_x)
.
How does a C++ reference look, memory-wise?: This answer suggests that compiler will try its best to save space.
c++ reference
c++ reference
edited Nov 22 at 6:46
asked Nov 21 at 22:52
ptr_user7813604
442118
442118
I suspect the answer is because you ran the code without turning on any optimizations.
– Mooing Duck
Nov 22 at 0:05
@MooingDuck: I was (re-)thinking about whether C++ would do the optimization as python before I fell asleep, then now I just wake up and realize that it should be either the converse/reverse question or C++ should handle it better. What's the canonical way/mechanism when C++ doing this?
– ptr_user7813604
Nov 22 at 3:57
1
By default, compilers generate unoptimized builds, which make it far easier to step through and debug. However, every compiler also has a flag you can pass telling it to build an optimized build, which will shrink it down and make it fast and small. How are you compiling your code?
– Mooing Duck
Nov 22 at 6:05
@MooingDuck: I just clicked run on ideone.com, I did try to find so called optimization options there but it seems like they don't have one. I haven't learned much about optimization since I rarely thinking about optimization.
– ptr_user7813604
Nov 22 at 6:11
1
ptr_user7813604 coliru.stacked-crooked.com lets you pass -O0 through -O3 flags to the compiler, letting you see various results. (-O0 is the default of no optimization, -O3 is the maximum optimizations)
– Mooing Duck
Nov 22 at 7:14
add a comment |
I suspect the answer is because you ran the code without turning on any optimizations.
– Mooing Duck
Nov 22 at 0:05
@MooingDuck: I was (re-)thinking about whether C++ would do the optimization as python before I fell asleep, then now I just wake up and realize that it should be either the converse/reverse question or C++ should handle it better. What's the canonical way/mechanism when C++ doing this?
– ptr_user7813604
Nov 22 at 3:57
1
By default, compilers generate unoptimized builds, which make it far easier to step through and debug. However, every compiler also has a flag you can pass telling it to build an optimized build, which will shrink it down and make it fast and small. How are you compiling your code?
– Mooing Duck
Nov 22 at 6:05
@MooingDuck: I just clicked run on ideone.com, I did try to find so called optimization options there but it seems like they don't have one. I haven't learned much about optimization since I rarely thinking about optimization.
– ptr_user7813604
Nov 22 at 6:11
1
ptr_user7813604 coliru.stacked-crooked.com lets you pass -O0 through -O3 flags to the compiler, letting you see various results. (-O0 is the default of no optimization, -O3 is the maximum optimizations)
– Mooing Duck
Nov 22 at 7:14
I suspect the answer is because you ran the code without turning on any optimizations.
– Mooing Duck
Nov 22 at 0:05
I suspect the answer is because you ran the code without turning on any optimizations.
– Mooing Duck
Nov 22 at 0:05
@MooingDuck: I was (re-)thinking about whether C++ would do the optimization as python before I fell asleep, then now I just wake up and realize that it should be either the converse/reverse question or C++ should handle it better. What's the canonical way/mechanism when C++ doing this?
– ptr_user7813604
Nov 22 at 3:57
@MooingDuck: I was (re-)thinking about whether C++ would do the optimization as python before I fell asleep, then now I just wake up and realize that it should be either the converse/reverse question or C++ should handle it better. What's the canonical way/mechanism when C++ doing this?
– ptr_user7813604
Nov 22 at 3:57
1
1
By default, compilers generate unoptimized builds, which make it far easier to step through and debug. However, every compiler also has a flag you can pass telling it to build an optimized build, which will shrink it down and make it fast and small. How are you compiling your code?
– Mooing Duck
Nov 22 at 6:05
By default, compilers generate unoptimized builds, which make it far easier to step through and debug. However, every compiler also has a flag you can pass telling it to build an optimized build, which will shrink it down and make it fast and small. How are you compiling your code?
– Mooing Duck
Nov 22 at 6:05
@MooingDuck: I just clicked run on ideone.com, I did try to find so called optimization options there but it seems like they don't have one. I haven't learned much about optimization since I rarely thinking about optimization.
– ptr_user7813604
Nov 22 at 6:11
@MooingDuck: I just clicked run on ideone.com, I did try to find so called optimization options there but it seems like they don't have one. I haven't learned much about optimization since I rarely thinking about optimization.
– ptr_user7813604
Nov 22 at 6:11
1
1
ptr_user7813604 coliru.stacked-crooked.com lets you pass -O0 through -O3 flags to the compiler, letting you see various results. (-O0 is the default of no optimization, -O3 is the maximum optimizations)
– Mooing Duck
Nov 22 at 7:14
ptr_user7813604 coliru.stacked-crooked.com lets you pass -O0 through -O3 flags to the compiler, letting you see various results. (-O0 is the default of no optimization, -O3 is the maximum optimizations)
– Mooing Duck
Nov 22 at 7:14
add a comment |
3 Answers
3
active
oldest
votes
up vote
6
down vote
accepted
Your 123
isn't a "constant". Rather, it is a literal. A literal forms an expression that is a prvalue (i.e. a temporary object initialized with the value of given by the literal). When you bind that expression to are reference, the lifetime of that object is extended to that of the reference, but the important point here is that each such object is a distinct object, and thus has a distinct address.
If you will, the text string "123" provides a rule for how to create objects, but it is not by itself an object. You can rewrite your code to make this more explicit:
const int & r = int(123); // temporary of type "int" and value "123"
(There's no single such thing as "a constant" in C++. There are lots of things that are constant in one way or another, but they all need more detailed consideration.)
So sinceconst
is just compile time checking it has nothing to do with constant?
– ptr_user7813604
Nov 21 at 23:05
1
A prvalue is an expression, not a temporary object. Also there may or may not be a temporary object materialized at some stage for a prvalue. Reference binding causes temporary materialization.
– M.M
Nov 21 at 23:18
@ptr_user7813604: I'd rather say that "constant" is too vague a term for that question to be meaningful. Lots of things can be constant in different ways in C++ (e.g. types, expressions, initialization).
– Kerrek SB
Nov 22 at 0:56
1
@ptr_user7813604: Maybe it helps if you think of literals as being part of the source code, but object creation as part of the runtime behaviour? Source code doesn't create objects, only execution does. The source code (in this case, the literal) determines how objects are created at runtime. Temporary objects are distinct by their very nature; a temporary object has no aliases. No two unrelated expressions denote the same temporary object (until you start binding the temporary to some reference). That's how the language has been designed.
– Kerrek SB
Nov 22 at 11:33
1
@ptr_user7813604: I'd say optimization is an unrelated topic that doesn't affect the present question, which is all about the object model and the nature of expressions in the language. All those are core parts of the C++ design. Ultimately the immediate answer is always "because that's how the language works", so perhaps a more satisfying question would be why the language has been designed this way. Temporary objects are not non-temporary objects in some global cache, they are truly temporary in the sense of being (newly, uniquely) created just at the point where they're needed.
– Kerrek SB
Nov 22 at 11:55
|
show 4 more comments
up vote
4
down vote
The literal is not an object. The references do not refer to the literal. When you initialise a reference using a literal, a temporary object will be created, and the lifetime of the temporary object is bound to the lifetime of the reference.
The objects (one local variable, two temporaries) are separate and distinct objects despite having the same value. Since they're separate, they occupy separate memory locations. The standard mandates this, and that makes it possible to identify and distinguish objects based on their memory address.
add a comment |
up vote
4
down vote
The three declaration statements:
const int &r1 = 123;
const int &r2 = 123;
const int &r3 = r2;
will initialize 3 temporary objects with lifetime extended to be equal to the scope of their respective variables. Now, there is a language rule that says:
Any two objects with overlapping lifetimes (that are not bit fields)
are guaranteed to have different addresses unless one of them is a
subobject of another or provides storage for another, or if they are
subobjects of different type within the same complete object, and one
of them is a zero-size base.
Since the references are bound to 3 distinct temporary, then you cannot observe these objects on overlapping addresses.
Interestingly, the As-if rule might probably permit the program to allocate all three temporary objects at the same address but only if your compiler and linker can theoretically prove that your program can never observe the these objects as allocated at the same address. In your example, this is infeasible since you print the address of the objects.
This remind me of quantum mechanics in a sense that my observation is part of the experiment. By the way I have trouble to understand this kind of language rule, ... are guaranteed to ... for what?
– ptr_user7813604
Nov 22 at 7:01
1
@ptr_user7813604 that's philosophical question and you will need to dive into C++ drafts and proposals to find answer. One of the probable reasons is that object identity can be used in computations - you can never distinguish r1 from r2 without having name if object they refer to is same.
– Euri Pinhollow
Nov 22 at 7:47
OK I like this reason, and I will make a further induction that then the compiler can only do optimization up to a theoretical limit, where everything is almost indistinguishable. btw I like philosophical question because it doesn't necessarily have an answer.
– ptr_user7813604
Nov 22 at 8:06
I don't understand your ["] Since the references are bound to 3 distinct temporary, then you cannot observe these objects on overlapping addresses. [."], does it mean that some of them has the same address?
– ptr_user7813604
Nov 22 at 8:16
@ptr_user7813604 "overlapping" refers not to the address of first byte but to the range of addresses objects occupy. This limitation means that no byte can be occupied by more than one object (except as said in excerpt).
– Euri Pinhollow
Nov 22 at 11:46
add a comment |
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
6
down vote
accepted
Your 123
isn't a "constant". Rather, it is a literal. A literal forms an expression that is a prvalue (i.e. a temporary object initialized with the value of given by the literal). When you bind that expression to are reference, the lifetime of that object is extended to that of the reference, but the important point here is that each such object is a distinct object, and thus has a distinct address.
If you will, the text string "123" provides a rule for how to create objects, but it is not by itself an object. You can rewrite your code to make this more explicit:
const int & r = int(123); // temporary of type "int" and value "123"
(There's no single such thing as "a constant" in C++. There are lots of things that are constant in one way or another, but they all need more detailed consideration.)
So sinceconst
is just compile time checking it has nothing to do with constant?
– ptr_user7813604
Nov 21 at 23:05
1
A prvalue is an expression, not a temporary object. Also there may or may not be a temporary object materialized at some stage for a prvalue. Reference binding causes temporary materialization.
– M.M
Nov 21 at 23:18
@ptr_user7813604: I'd rather say that "constant" is too vague a term for that question to be meaningful. Lots of things can be constant in different ways in C++ (e.g. types, expressions, initialization).
– Kerrek SB
Nov 22 at 0:56
1
@ptr_user7813604: Maybe it helps if you think of literals as being part of the source code, but object creation as part of the runtime behaviour? Source code doesn't create objects, only execution does. The source code (in this case, the literal) determines how objects are created at runtime. Temporary objects are distinct by their very nature; a temporary object has no aliases. No two unrelated expressions denote the same temporary object (until you start binding the temporary to some reference). That's how the language has been designed.
– Kerrek SB
Nov 22 at 11:33
1
@ptr_user7813604: I'd say optimization is an unrelated topic that doesn't affect the present question, which is all about the object model and the nature of expressions in the language. All those are core parts of the C++ design. Ultimately the immediate answer is always "because that's how the language works", so perhaps a more satisfying question would be why the language has been designed this way. Temporary objects are not non-temporary objects in some global cache, they are truly temporary in the sense of being (newly, uniquely) created just at the point where they're needed.
– Kerrek SB
Nov 22 at 11:55
|
show 4 more comments
up vote
6
down vote
accepted
Your 123
isn't a "constant". Rather, it is a literal. A literal forms an expression that is a prvalue (i.e. a temporary object initialized with the value of given by the literal). When you bind that expression to are reference, the lifetime of that object is extended to that of the reference, but the important point here is that each such object is a distinct object, and thus has a distinct address.
If you will, the text string "123" provides a rule for how to create objects, but it is not by itself an object. You can rewrite your code to make this more explicit:
const int & r = int(123); // temporary of type "int" and value "123"
(There's no single such thing as "a constant" in C++. There are lots of things that are constant in one way or another, but they all need more detailed consideration.)
So sinceconst
is just compile time checking it has nothing to do with constant?
– ptr_user7813604
Nov 21 at 23:05
1
A prvalue is an expression, not a temporary object. Also there may or may not be a temporary object materialized at some stage for a prvalue. Reference binding causes temporary materialization.
– M.M
Nov 21 at 23:18
@ptr_user7813604: I'd rather say that "constant" is too vague a term for that question to be meaningful. Lots of things can be constant in different ways in C++ (e.g. types, expressions, initialization).
– Kerrek SB
Nov 22 at 0:56
1
@ptr_user7813604: Maybe it helps if you think of literals as being part of the source code, but object creation as part of the runtime behaviour? Source code doesn't create objects, only execution does. The source code (in this case, the literal) determines how objects are created at runtime. Temporary objects are distinct by their very nature; a temporary object has no aliases. No two unrelated expressions denote the same temporary object (until you start binding the temporary to some reference). That's how the language has been designed.
– Kerrek SB
Nov 22 at 11:33
1
@ptr_user7813604: I'd say optimization is an unrelated topic that doesn't affect the present question, which is all about the object model and the nature of expressions in the language. All those are core parts of the C++ design. Ultimately the immediate answer is always "because that's how the language works", so perhaps a more satisfying question would be why the language has been designed this way. Temporary objects are not non-temporary objects in some global cache, they are truly temporary in the sense of being (newly, uniquely) created just at the point where they're needed.
– Kerrek SB
Nov 22 at 11:55
|
show 4 more comments
up vote
6
down vote
accepted
up vote
6
down vote
accepted
Your 123
isn't a "constant". Rather, it is a literal. A literal forms an expression that is a prvalue (i.e. a temporary object initialized with the value of given by the literal). When you bind that expression to are reference, the lifetime of that object is extended to that of the reference, but the important point here is that each such object is a distinct object, and thus has a distinct address.
If you will, the text string "123" provides a rule for how to create objects, but it is not by itself an object. You can rewrite your code to make this more explicit:
const int & r = int(123); // temporary of type "int" and value "123"
(There's no single such thing as "a constant" in C++. There are lots of things that are constant in one way or another, but they all need more detailed consideration.)
Your 123
isn't a "constant". Rather, it is a literal. A literal forms an expression that is a prvalue (i.e. a temporary object initialized with the value of given by the literal). When you bind that expression to are reference, the lifetime of that object is extended to that of the reference, but the important point here is that each such object is a distinct object, and thus has a distinct address.
If you will, the text string "123" provides a rule for how to create objects, but it is not by itself an object. You can rewrite your code to make this more explicit:
const int & r = int(123); // temporary of type "int" and value "123"
(There's no single such thing as "a constant" in C++. There are lots of things that are constant in one way or another, but they all need more detailed consideration.)
answered Nov 21 at 22:58
Kerrek SB
360k60675912
360k60675912
So sinceconst
is just compile time checking it has nothing to do with constant?
– ptr_user7813604
Nov 21 at 23:05
1
A prvalue is an expression, not a temporary object. Also there may or may not be a temporary object materialized at some stage for a prvalue. Reference binding causes temporary materialization.
– M.M
Nov 21 at 23:18
@ptr_user7813604: I'd rather say that "constant" is too vague a term for that question to be meaningful. Lots of things can be constant in different ways in C++ (e.g. types, expressions, initialization).
– Kerrek SB
Nov 22 at 0:56
1
@ptr_user7813604: Maybe it helps if you think of literals as being part of the source code, but object creation as part of the runtime behaviour? Source code doesn't create objects, only execution does. The source code (in this case, the literal) determines how objects are created at runtime. Temporary objects are distinct by their very nature; a temporary object has no aliases. No two unrelated expressions denote the same temporary object (until you start binding the temporary to some reference). That's how the language has been designed.
– Kerrek SB
Nov 22 at 11:33
1
@ptr_user7813604: I'd say optimization is an unrelated topic that doesn't affect the present question, which is all about the object model and the nature of expressions in the language. All those are core parts of the C++ design. Ultimately the immediate answer is always "because that's how the language works", so perhaps a more satisfying question would be why the language has been designed this way. Temporary objects are not non-temporary objects in some global cache, they are truly temporary in the sense of being (newly, uniquely) created just at the point where they're needed.
– Kerrek SB
Nov 22 at 11:55
|
show 4 more comments
So sinceconst
is just compile time checking it has nothing to do with constant?
– ptr_user7813604
Nov 21 at 23:05
1
A prvalue is an expression, not a temporary object. Also there may or may not be a temporary object materialized at some stage for a prvalue. Reference binding causes temporary materialization.
– M.M
Nov 21 at 23:18
@ptr_user7813604: I'd rather say that "constant" is too vague a term for that question to be meaningful. Lots of things can be constant in different ways in C++ (e.g. types, expressions, initialization).
– Kerrek SB
Nov 22 at 0:56
1
@ptr_user7813604: Maybe it helps if you think of literals as being part of the source code, but object creation as part of the runtime behaviour? Source code doesn't create objects, only execution does. The source code (in this case, the literal) determines how objects are created at runtime. Temporary objects are distinct by their very nature; a temporary object has no aliases. No two unrelated expressions denote the same temporary object (until you start binding the temporary to some reference). That's how the language has been designed.
– Kerrek SB
Nov 22 at 11:33
1
@ptr_user7813604: I'd say optimization is an unrelated topic that doesn't affect the present question, which is all about the object model and the nature of expressions in the language. All those are core parts of the C++ design. Ultimately the immediate answer is always "because that's how the language works", so perhaps a more satisfying question would be why the language has been designed this way. Temporary objects are not non-temporary objects in some global cache, they are truly temporary in the sense of being (newly, uniquely) created just at the point where they're needed.
– Kerrek SB
Nov 22 at 11:55
So since
const
is just compile time checking it has nothing to do with constant?– ptr_user7813604
Nov 21 at 23:05
So since
const
is just compile time checking it has nothing to do with constant?– ptr_user7813604
Nov 21 at 23:05
1
1
A prvalue is an expression, not a temporary object. Also there may or may not be a temporary object materialized at some stage for a prvalue. Reference binding causes temporary materialization.
– M.M
Nov 21 at 23:18
A prvalue is an expression, not a temporary object. Also there may or may not be a temporary object materialized at some stage for a prvalue. Reference binding causes temporary materialization.
– M.M
Nov 21 at 23:18
@ptr_user7813604: I'd rather say that "constant" is too vague a term for that question to be meaningful. Lots of things can be constant in different ways in C++ (e.g. types, expressions, initialization).
– Kerrek SB
Nov 22 at 0:56
@ptr_user7813604: I'd rather say that "constant" is too vague a term for that question to be meaningful. Lots of things can be constant in different ways in C++ (e.g. types, expressions, initialization).
– Kerrek SB
Nov 22 at 0:56
1
1
@ptr_user7813604: Maybe it helps if you think of literals as being part of the source code, but object creation as part of the runtime behaviour? Source code doesn't create objects, only execution does. The source code (in this case, the literal) determines how objects are created at runtime. Temporary objects are distinct by their very nature; a temporary object has no aliases. No two unrelated expressions denote the same temporary object (until you start binding the temporary to some reference). That's how the language has been designed.
– Kerrek SB
Nov 22 at 11:33
@ptr_user7813604: Maybe it helps if you think of literals as being part of the source code, but object creation as part of the runtime behaviour? Source code doesn't create objects, only execution does. The source code (in this case, the literal) determines how objects are created at runtime. Temporary objects are distinct by their very nature; a temporary object has no aliases. No two unrelated expressions denote the same temporary object (until you start binding the temporary to some reference). That's how the language has been designed.
– Kerrek SB
Nov 22 at 11:33
1
1
@ptr_user7813604: I'd say optimization is an unrelated topic that doesn't affect the present question, which is all about the object model and the nature of expressions in the language. All those are core parts of the C++ design. Ultimately the immediate answer is always "because that's how the language works", so perhaps a more satisfying question would be why the language has been designed this way. Temporary objects are not non-temporary objects in some global cache, they are truly temporary in the sense of being (newly, uniquely) created just at the point where they're needed.
– Kerrek SB
Nov 22 at 11:55
@ptr_user7813604: I'd say optimization is an unrelated topic that doesn't affect the present question, which is all about the object model and the nature of expressions in the language. All those are core parts of the C++ design. Ultimately the immediate answer is always "because that's how the language works", so perhaps a more satisfying question would be why the language has been designed this way. Temporary objects are not non-temporary objects in some global cache, they are truly temporary in the sense of being (newly, uniquely) created just at the point where they're needed.
– Kerrek SB
Nov 22 at 11:55
|
show 4 more comments
up vote
4
down vote
The literal is not an object. The references do not refer to the literal. When you initialise a reference using a literal, a temporary object will be created, and the lifetime of the temporary object is bound to the lifetime of the reference.
The objects (one local variable, two temporaries) are separate and distinct objects despite having the same value. Since they're separate, they occupy separate memory locations. The standard mandates this, and that makes it possible to identify and distinguish objects based on their memory address.
add a comment |
up vote
4
down vote
The literal is not an object. The references do not refer to the literal. When you initialise a reference using a literal, a temporary object will be created, and the lifetime of the temporary object is bound to the lifetime of the reference.
The objects (one local variable, two temporaries) are separate and distinct objects despite having the same value. Since they're separate, they occupy separate memory locations. The standard mandates this, and that makes it possible to identify and distinguish objects based on their memory address.
add a comment |
up vote
4
down vote
up vote
4
down vote
The literal is not an object. The references do not refer to the literal. When you initialise a reference using a literal, a temporary object will be created, and the lifetime of the temporary object is bound to the lifetime of the reference.
The objects (one local variable, two temporaries) are separate and distinct objects despite having the same value. Since they're separate, they occupy separate memory locations. The standard mandates this, and that makes it possible to identify and distinguish objects based on their memory address.
The literal is not an object. The references do not refer to the literal. When you initialise a reference using a literal, a temporary object will be created, and the lifetime of the temporary object is bound to the lifetime of the reference.
The objects (one local variable, two temporaries) are separate and distinct objects despite having the same value. Since they're separate, they occupy separate memory locations. The standard mandates this, and that makes it possible to identify and distinguish objects based on their memory address.
edited Nov 21 at 23:57
answered Nov 21 at 23:00
eerorika
74.8k555116
74.8k555116
add a comment |
add a comment |
up vote
4
down vote
The three declaration statements:
const int &r1 = 123;
const int &r2 = 123;
const int &r3 = r2;
will initialize 3 temporary objects with lifetime extended to be equal to the scope of their respective variables. Now, there is a language rule that says:
Any two objects with overlapping lifetimes (that are not bit fields)
are guaranteed to have different addresses unless one of them is a
subobject of another or provides storage for another, or if they are
subobjects of different type within the same complete object, and one
of them is a zero-size base.
Since the references are bound to 3 distinct temporary, then you cannot observe these objects on overlapping addresses.
Interestingly, the As-if rule might probably permit the program to allocate all three temporary objects at the same address but only if your compiler and linker can theoretically prove that your program can never observe the these objects as allocated at the same address. In your example, this is infeasible since you print the address of the objects.
This remind me of quantum mechanics in a sense that my observation is part of the experiment. By the way I have trouble to understand this kind of language rule, ... are guaranteed to ... for what?
– ptr_user7813604
Nov 22 at 7:01
1
@ptr_user7813604 that's philosophical question and you will need to dive into C++ drafts and proposals to find answer. One of the probable reasons is that object identity can be used in computations - you can never distinguish r1 from r2 without having name if object they refer to is same.
– Euri Pinhollow
Nov 22 at 7:47
OK I like this reason, and I will make a further induction that then the compiler can only do optimization up to a theoretical limit, where everything is almost indistinguishable. btw I like philosophical question because it doesn't necessarily have an answer.
– ptr_user7813604
Nov 22 at 8:06
I don't understand your ["] Since the references are bound to 3 distinct temporary, then you cannot observe these objects on overlapping addresses. [."], does it mean that some of them has the same address?
– ptr_user7813604
Nov 22 at 8:16
@ptr_user7813604 "overlapping" refers not to the address of first byte but to the range of addresses objects occupy. This limitation means that no byte can be occupied by more than one object (except as said in excerpt).
– Euri Pinhollow
Nov 22 at 11:46
add a comment |
up vote
4
down vote
The three declaration statements:
const int &r1 = 123;
const int &r2 = 123;
const int &r3 = r2;
will initialize 3 temporary objects with lifetime extended to be equal to the scope of their respective variables. Now, there is a language rule that says:
Any two objects with overlapping lifetimes (that are not bit fields)
are guaranteed to have different addresses unless one of them is a
subobject of another or provides storage for another, or if they are
subobjects of different type within the same complete object, and one
of them is a zero-size base.
Since the references are bound to 3 distinct temporary, then you cannot observe these objects on overlapping addresses.
Interestingly, the As-if rule might probably permit the program to allocate all three temporary objects at the same address but only if your compiler and linker can theoretically prove that your program can never observe the these objects as allocated at the same address. In your example, this is infeasible since you print the address of the objects.
This remind me of quantum mechanics in a sense that my observation is part of the experiment. By the way I have trouble to understand this kind of language rule, ... are guaranteed to ... for what?
– ptr_user7813604
Nov 22 at 7:01
1
@ptr_user7813604 that's philosophical question and you will need to dive into C++ drafts and proposals to find answer. One of the probable reasons is that object identity can be used in computations - you can never distinguish r1 from r2 without having name if object they refer to is same.
– Euri Pinhollow
Nov 22 at 7:47
OK I like this reason, and I will make a further induction that then the compiler can only do optimization up to a theoretical limit, where everything is almost indistinguishable. btw I like philosophical question because it doesn't necessarily have an answer.
– ptr_user7813604
Nov 22 at 8:06
I don't understand your ["] Since the references are bound to 3 distinct temporary, then you cannot observe these objects on overlapping addresses. [."], does it mean that some of them has the same address?
– ptr_user7813604
Nov 22 at 8:16
@ptr_user7813604 "overlapping" refers not to the address of first byte but to the range of addresses objects occupy. This limitation means that no byte can be occupied by more than one object (except as said in excerpt).
– Euri Pinhollow
Nov 22 at 11:46
add a comment |
up vote
4
down vote
up vote
4
down vote
The three declaration statements:
const int &r1 = 123;
const int &r2 = 123;
const int &r3 = r2;
will initialize 3 temporary objects with lifetime extended to be equal to the scope of their respective variables. Now, there is a language rule that says:
Any two objects with overlapping lifetimes (that are not bit fields)
are guaranteed to have different addresses unless one of them is a
subobject of another or provides storage for another, or if they are
subobjects of different type within the same complete object, and one
of them is a zero-size base.
Since the references are bound to 3 distinct temporary, then you cannot observe these objects on overlapping addresses.
Interestingly, the As-if rule might probably permit the program to allocate all three temporary objects at the same address but only if your compiler and linker can theoretically prove that your program can never observe the these objects as allocated at the same address. In your example, this is infeasible since you print the address of the objects.
The three declaration statements:
const int &r1 = 123;
const int &r2 = 123;
const int &r3 = r2;
will initialize 3 temporary objects with lifetime extended to be equal to the scope of their respective variables. Now, there is a language rule that says:
Any two objects with overlapping lifetimes (that are not bit fields)
are guaranteed to have different addresses unless one of them is a
subobject of another or provides storage for another, or if they are
subobjects of different type within the same complete object, and one
of them is a zero-size base.
Since the references are bound to 3 distinct temporary, then you cannot observe these objects on overlapping addresses.
Interestingly, the As-if rule might probably permit the program to allocate all three temporary objects at the same address but only if your compiler and linker can theoretically prove that your program can never observe the these objects as allocated at the same address. In your example, this is infeasible since you print the address of the objects.
answered Nov 22 at 0:26
Julien Villemure-Fréchette
36517
36517
This remind me of quantum mechanics in a sense that my observation is part of the experiment. By the way I have trouble to understand this kind of language rule, ... are guaranteed to ... for what?
– ptr_user7813604
Nov 22 at 7:01
1
@ptr_user7813604 that's philosophical question and you will need to dive into C++ drafts and proposals to find answer. One of the probable reasons is that object identity can be used in computations - you can never distinguish r1 from r2 without having name if object they refer to is same.
– Euri Pinhollow
Nov 22 at 7:47
OK I like this reason, and I will make a further induction that then the compiler can only do optimization up to a theoretical limit, where everything is almost indistinguishable. btw I like philosophical question because it doesn't necessarily have an answer.
– ptr_user7813604
Nov 22 at 8:06
I don't understand your ["] Since the references are bound to 3 distinct temporary, then you cannot observe these objects on overlapping addresses. [."], does it mean that some of them has the same address?
– ptr_user7813604
Nov 22 at 8:16
@ptr_user7813604 "overlapping" refers not to the address of first byte but to the range of addresses objects occupy. This limitation means that no byte can be occupied by more than one object (except as said in excerpt).
– Euri Pinhollow
Nov 22 at 11:46
add a comment |
This remind me of quantum mechanics in a sense that my observation is part of the experiment. By the way I have trouble to understand this kind of language rule, ... are guaranteed to ... for what?
– ptr_user7813604
Nov 22 at 7:01
1
@ptr_user7813604 that's philosophical question and you will need to dive into C++ drafts and proposals to find answer. One of the probable reasons is that object identity can be used in computations - you can never distinguish r1 from r2 without having name if object they refer to is same.
– Euri Pinhollow
Nov 22 at 7:47
OK I like this reason, and I will make a further induction that then the compiler can only do optimization up to a theoretical limit, where everything is almost indistinguishable. btw I like philosophical question because it doesn't necessarily have an answer.
– ptr_user7813604
Nov 22 at 8:06
I don't understand your ["] Since the references are bound to 3 distinct temporary, then you cannot observe these objects on overlapping addresses. [."], does it mean that some of them has the same address?
– ptr_user7813604
Nov 22 at 8:16
@ptr_user7813604 "overlapping" refers not to the address of first byte but to the range of addresses objects occupy. This limitation means that no byte can be occupied by more than one object (except as said in excerpt).
– Euri Pinhollow
Nov 22 at 11:46
This remind me of quantum mechanics in a sense that my observation is part of the experiment. By the way I have trouble to understand this kind of language rule, ... are guaranteed to ... for what?
– ptr_user7813604
Nov 22 at 7:01
This remind me of quantum mechanics in a sense that my observation is part of the experiment. By the way I have trouble to understand this kind of language rule, ... are guaranteed to ... for what?
– ptr_user7813604
Nov 22 at 7:01
1
1
@ptr_user7813604 that's philosophical question and you will need to dive into C++ drafts and proposals to find answer. One of the probable reasons is that object identity can be used in computations - you can never distinguish r1 from r2 without having name if object they refer to is same.
– Euri Pinhollow
Nov 22 at 7:47
@ptr_user7813604 that's philosophical question and you will need to dive into C++ drafts and proposals to find answer. One of the probable reasons is that object identity can be used in computations - you can never distinguish r1 from r2 without having name if object they refer to is same.
– Euri Pinhollow
Nov 22 at 7:47
OK I like this reason, and I will make a further induction that then the compiler can only do optimization up to a theoretical limit, where everything is almost indistinguishable. btw I like philosophical question because it doesn't necessarily have an answer.
– ptr_user7813604
Nov 22 at 8:06
OK I like this reason, and I will make a further induction that then the compiler can only do optimization up to a theoretical limit, where everything is almost indistinguishable. btw I like philosophical question because it doesn't necessarily have an answer.
– ptr_user7813604
Nov 22 at 8:06
I don't understand your ["] Since the references are bound to 3 distinct temporary, then you cannot observe these objects on overlapping addresses. [."], does it mean that some of them has the same address?
– ptr_user7813604
Nov 22 at 8:16
I don't understand your ["] Since the references are bound to 3 distinct temporary, then you cannot observe these objects on overlapping addresses. [."], does it mean that some of them has the same address?
– ptr_user7813604
Nov 22 at 8:16
@ptr_user7813604 "overlapping" refers not to the address of first byte but to the range of addresses objects occupy. This limitation means that no byte can be occupied by more than one object (except as said in excerpt).
– Euri Pinhollow
Nov 22 at 11:46
@ptr_user7813604 "overlapping" refers not to the address of first byte but to the range of addresses objects occupy. This limitation means that no byte can be occupied by more than one object (except as said in excerpt).
– Euri Pinhollow
Nov 22 at 11:46
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53421559%2fwhy-references-to-the-same-constant-take-distinct-memory-space-in-c%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
I suspect the answer is because you ran the code without turning on any optimizations.
– Mooing Duck
Nov 22 at 0:05
@MooingDuck: I was (re-)thinking about whether C++ would do the optimization as python before I fell asleep, then now I just wake up and realize that it should be either the converse/reverse question or C++ should handle it better. What's the canonical way/mechanism when C++ doing this?
– ptr_user7813604
Nov 22 at 3:57
1
By default, compilers generate unoptimized builds, which make it far easier to step through and debug. However, every compiler also has a flag you can pass telling it to build an optimized build, which will shrink it down and make it fast and small. How are you compiling your code?
– Mooing Duck
Nov 22 at 6:05
@MooingDuck: I just clicked run on ideone.com, I did try to find so called optimization options there but it seems like they don't have one. I haven't learned much about optimization since I rarely thinking about optimization.
– ptr_user7813604
Nov 22 at 6:11
1
ptr_user7813604 coliru.stacked-crooked.com lets you pass -O0 through -O3 flags to the compiler, letting you see various results. (-O0 is the default of no optimization, -O3 is the maximum optimizations)
– Mooing Duck
Nov 22 at 7:14