为什么80%的码农都做不了架构师?>>>
That is, an object is a contiguous region of
storage; an lvalue is an expression that refers to an object. The word
“lvalue” was originally coined to mean “something that can be on the
left-hand side of an assignment.” However, not every lvalue may be
used on the left-hand side of an assignment; an lvalue can refer to a
constant (§7.7). An lvalue that has not been declared const is often
called a modifiable lvalue . This simple and low-level notion of an
object should not be confused with the notions of class object and
object of polymorphic type (§3.2.2, §20.3.2).
To complement the notion of an lvalue, we have the notion of an
rvalue . Roughly, rvalue means “a value that is not an lvalue,” such as
a temporary value (e.g., the value returned by a function).
If you need to be more technical (say, because you want to read
the ISO C++ standard), you need a more refined view of lvalue and
rvalue. There are two properties that matter for an object when it
comes to addressing, copying, and moving:
• Has identity : The program has the name of, pointer to, or
reference to the object so that it is possible to determine if two
objects are the same, whether the value of the object has
changed, etc.
• Movable : The object may be moved from (i.e., we are allowed
to move its value to another location and leave the object in a
valid but unspecified state, rather than copying; §17.5).
It turns out that three of the four possible combinations of those two
properties are needed to precisely describe the C++ language rules
(we have no need for objects that do not have identity and cannot
be moved). Using “m for movable” and “i for has identity,” we can
represent this classification of expressions graphically:
So, a classical lvalue is something that has identity and cannot be
moved (because we could examine it after a move), and a classical
rvalue is anything that we are allowed to move from. The other
alternatives are prvalue (“pure rvalue”), glvalue (“generalized lvalue”),
and xvalue (“x” for “extraordinary” or “expert only”; the suggestions
for the meaning of this “x” have been quite imaginative).
The lifetime of an object starts when its constructor completes and
ends when its destructor starts executing. Objects of types without a
declared constructor, such as an int, can be considered to have
default constructors and destructors that do nothing.
We can classify objects based on their lifetimes:
• Automatic : Unless the programmer specifies otherwise (§12.1.8,
§16.2.12), an object declared in a function is created when its
definition is encountered and destroyed when its name goes out
of scope. Such objects are sometimes called automatic objects.
In a typical implementation, automatic objects are allocated on
the stack; each call of the function gets its own stack frame to
hold its automatic objects.
• Static : Objects declared in global or namespace scope (§6.3.4)
and statics declared in functions (§12.1.8) or classes (§16.2.12)
are created and initialized once (only) and “live” until the
program terminates (§15.4.3). Such objects are called static
objects. A static object has the same address throughout the life
of a program execution. Static objects can cause serious
problems in a multi-threaded program because they are shared
among all threads and typically require locking to avoid data
races (§5.3.1, §42.3).
• Free store : Using the new and delete operators, we can create
objects whose lifetimes are controlled directly (§11.2).
• Temporary objects (e.g., intermediate results in a computation
or an object used to hold a value for a reference to const
argument): their lifetime is determined by their use. If they are
bound to a reference, their lifetime is that of the reference;
otherwise, they “live” until the end of the full expression of
which they are part. A full expression is an expression that is not
part of another expression. Typically, temporary objects are
automatic.
• Thread-local objects; that is, objects declared thread_local
(§42.2.8): such objects are created when their thread is and
destroyed when their thread is.
Static and automatic are traditionally referred to as storage classes .
Array elements and nonstatic class members have their lifetimes
determined by the object of which they are part.
Static and automatic are traditionally referred to as storage classes .
Array elements and nonstatic class members have their lifetimes
determined by the object of which they are part.