问题
int x = 12;
12
is said to be integer literal, and therefore can't be used in the LValue.
- How does the compiler allocate memory to a literals?
- What is the scope of a literals?
- Why can't we get its address with an &12 in its scope?
回答1:
OK Bad example in the question.
But the question is still valid:
Lets try:
Foo getFoo() {return Foo();}
int func()
{
getFoo().bar(); // Creates temporary.
// before this comment it is also destroyed.
// But it lives for the whole expression above
// So you can call bar() on it.
}
int func2()
{
Foo const& tmp = getFoo(); // Creates temporary.
// Does not die here as it is bound to a const reference.
DO STUFF
} // tmp goes out of scope and temporary object destroyed.
// It lives to here because it is bound to a const reference.
How does the compiler allocate memory to a temporary object?
Undefined up-to the compiler.
But it would be real easy to allocate a tiny bit more memory onto the stack frame and hold it there. Then destroy it and reduce the size of the stack frame (though this answer makes a whole lot of assumptions about the underlying hardware that you should never do (best just to think of it as the compiler doing magic)).
What is the scope of a temporary object?
The temporary object lives until the end of the expression (usually the ;
) unless it is bound to a const reference. If it is bound to a const reference then it lives to then end of the scope that the reference belongs too (with a few exceptions (like constructors)).
Why can't we get its address with an &12 in its scope?
In the question 12 is not a temporay object.
It is an integer literal.
回答2:
In your example 12
is an integer literal. Integer literals are almost always "embedded" in machine instructions as an immediate operand. They are not stored in memory hence you can't access it through and address nor do they have a scope.
int x = 12
would translate to something like
movl 12 address_of_x_or_register
in almost all architectures. Here 12 is encoded as part of the instruction.
Just to be clear, x
still resides in the memory (stack in case of local variables or the data segment in case of global-variables) and would eventually contains the value 12
. The RHS "object" 12 is the integer literal and it doesn't reside in memory before or during the instruction, but "resides" in the instruction itself.
回答3:
1. How does the compiler allocate memory to a temporary object?
string myString = "hello";
In this case, a conversion constructor
is called to initialize a new object.
2. What is the scope of a temporary object?
The life of the temporary object is until the semi-colon
3. Why can't we get its address with an &12 in its scope? (in this case "hello")
&12
is not an object, it is the parameter given to the conversion constructor
回答4:
So, during compilation what does the compiler do to it? Storage?
This is really difficult to answer. The compiler will optomize the code as much as possible (the amount or level of optomization performed can often be set in your compiler tool).
For an example like the one given, if x can be substituted in the assembly instructions by 12, then x is "optomized out" and 12 is used as a direct replacement for x.
The "volatile" keyword can be used to trick the compiler into checking x every time it is used in the code. This will generate larger programs but might be useful to help you assign a memory location (storage) for your variable.
回答5:
Object is "something in memory". It means that this something occupies part of the process address space (either in stack or in 'free' memory). Also it means that you can get an address of it if you want to.
Temporary objects are just objects. Compiler generates the code to create them if it need such objects to calculate an expression:
void f(const string&);
void g()
{
f(string("Hello"));
}
The expression which calls f() will lead to generation of code which:
- creates temporary string object. Constructor is called with const char* as parameter;
- calls f() with a reference to this temporary object as parameter;
- destroys temporary string object.
The key part of this is the destruction of temporary object at the end of expression evaluation. Temporary object only exists in the expression itself (that is their makeshift scope). You may try something like: const string* ps = &string("Hello")
but your compiler will probably sound an alarm, because such expression will lead to creation of pointer which references memory that was occupied with temporary object but is not occupied by it anymore. It may still contain the string object members or may be overwritten by the following expressions in a program (not to mention that the destruction of temporary object will free the memory allocated in heap by the object). Using ps
will lead to undefined behavior.
The other question that arises here is the nature of objects in an expression like int x = 12
. In this case x may be an object or may be not. That depends on the compiler settings and on the code following the line. Compiler may deside to place x in register. In such case x will not be an object, cause registers have no addresses (on most platforms at least). If you don't change the value of x
compiler may even deside to use 12 in instructions directly. So '12' will only exists as a part of instruction codes.
Anyway, no matter what happens in the following code, int x = 12
will not create temporary 12
object. If compiler desides to place 12 in memory the instruction will be like (pseudo code):
store immediate address_of_x, 12
In case of an x plased in register you will have:
move immediate regX, 12
In both cases, 12 will be a part of the instruction (of compiled code chunk). Thus it will not be a separate object.
回答6:
Be careful, as other answers mostly cleared your misconceptions, but not this one:
What is the scope of a literals?
This question makes no sense, as the scope is a property of names (variables names, functions names, types names, templates names, namespaces names...).
A literal is a notation for a number, not a name.
来源:https://stackoverflow.com/questions/8571796/what-is-the-scope-of-a-literal-value-and-how-does-the-compiler-allocate-memory