5.3 Unary expressions
|
[expr.unary]
|
-
Expressions with unary operators group righttoleft.
unaryexpression:
postfixexpression
++ castexpression
castexpression
unaryoperator castexpression
sizeof unaryexpression
sizeof ( typeid )
newexpression
deleteexpression
unaryoperator: one of
* & + ! ~
5.3.1 Unary operators
|
[expr.unary.op]
|
-
The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function to which the expression points.
If the type of the expression is "pointer to T," the type of the result is "T." [Note: a pointer to an incomplete type (other than cv void ) can be dereferenced.
The lvalue thus obtained can be used in limited ways (to initialize a reference, for example); this lvalue must not be converted to an rvalue, see 4.1. ]
-
The result of the unary & operator is a pointer to its operand.
The operand shall be an lvalue or a qualifiedid.
In the first case, if the type of the expression is "T," the type of the result is "pointer to T".
In particular, the address of an object of type "cv T" is "pointer to cv T", with the same cvqualifiers.
For a qualifiedid, if the member is a static member of type "T", the type of the result is plain "pointer to T.".
If the member is a nonstatic member of class C of type T, the type of the result is "pointer to member of class C of type T".
[Example:
struct A { int i; };
struct B : A { };
... &B::i ... // has type int A::*
--end example]
[Note: a pointer to member formed from a mutable nonstatic data member (7.1.1) does not reflect the mutable specifier associated with the nonstatic data member. ]
-
A pointer to member is only formed when an explicit & is used and its operand is a qualifiedid not enclosed in parentheses.
[Note: that is, the expression &(qualifiedid), where the qualifiedid is enclosed in parentheses, does not form an expression of type "pointer to member".
Neither does qualifiedid, because there is no implicit conversion from a qualifiedid for a nonstatic member function to the type "pointer to member function" as there is from an lvalue of function type to the type "pointer to function" (4.3).
Nor is &unqualifiedid a pointer to member, even within the scope of the unqualifiedid's class. ]
-
The address of an object of incomplete type can be taken, but if the complete type of that object is a class type that declares operator&() as a member function, then the behavior is undefined (and no diagnostic is required).
The operand of & shall not be a bitfield.
-
The address of an overloaded function (clause 13) can be taken only in a context that uniquely determines which version of the overloaded function is referred to (see 13.4).
[Note: since the context might determine whether the operand is a static or nonstatic member function, the context can also affect whether the expression has type "pointer to function" or "pointer to member function." ]
-
The operand of the unary + operator shall have arithmetic, enumeration, or pointer type and the result is the value of the argument.
Integral promotion is performed on integral or enumeration operands.
The type of the result is the type of the promoted operand.
-
The operand of the unary operator shall have arithmetic or enumeration type and the result is the negation of its operand.
Integral promotion is performed on integral or enumeration operands.
The negative of an unsigned quantity is computed by subtracting its value from 2 n , where n is the number of bits in the promoted operand.
The type of the result is the type of the promoted operand.
-
The operand of the logical negation operator ! is implicitly converted to bool (clause 4); its value is true if the converted operand is false and false otherwise.
The type of the result is bool.
-
The operand of ~ shall have integral or enumeration type; the result is the one's complement of its operand.
Integral promotions are performed.
The type of the result is the type of the promoted operand.
There is an ambiguity in the unaryexpression ~X(), where X is a classname. The ambiguity is resolved in favor of treating ~ as a unary complement rather than treating ~X as referring to a destructor.
5.3.2 Increment and decrement
|
[expr.pre.incr]
|
-
The operand of prefix ++ is modified by adding 1, or set to true if it is bool (this use is deprecated).
The operand shall be a modifiable lvalue.
The type of the operand shall be an arithmetic type or a pointer to a completelydefined object type.
The value is the new value of the operand; it is an lvalue.
If x is not of type bool, the expression ++ x is equivalent to x += 1.
[Note: see the discussions of addition (5.7) and assignment operators (5.17) for information on conversions. ]
-
The operand of prefix is modified by subtracting 1.
The operand shall not be of type bool.
The requirements on the operand of prefix and the properties of its result are otherwise the same as those of prefix ++.
[Note: For postfix increment and decrement, see 5.2.6. ]
5.3.3 Sizeof
|
[expr.sizeof]
|
-
The sizeof operator yields the number of bytes in the object representation of its operand.
The operand is either an expression, which is not evaluated, or a parenthesized typeid.
The sizeof operator shall not be applied to an expression that has function or incomplete type, or to an enumeration type before all its enumerators have been declared, or to the parenthesized name of such types, or to an lvalue that designates a bitfield.
sizeof(char), sizeof(signed char) and sizeof(unsigned char) are 1; the result of sizeof applied to any other fundamental type (3.9.1) is implementationdefined.
[Note: in particular, sizeof(bool) and sizeof(wchar_t) are implementationdefined. 69) ]
[Note: See 1.7 for the definition of byte and 3.9 for the definition of object representation. ]
-
When applied to a reference or a reference type, the result is the size of the referenced type.
When applied to a class, the result is the number of bytes in an object of that class including any padding required for placing objects of that type in an array.
The size of a most derived class shall be greater than zero (1.8).
The result of applying sizeof to a base class subobject is the size of the base class type 70).
When applied to an array, the result is the total number of bytes in the array.
This implies that the size of an array of n elements is n times the size of an element.
-
The sizeof operator can be applied to a pointer to a function, but shall not be applied directly to a function.
-
The lvaluetorvalue (4.1), arraytopointer (4.2), and functiontopointer (4.3) standard conversions are not applied to the operand of sizeof.
-
Types shall not be defined in a sizeof expression.
-
The result is a constant of type size_t.
[Note: size_t is defined in the standard header <cstddef> (18.1).]
-
The newexpression attempts to create an object of the typeid (8.1) or newtypeid to which it is applied.
The type of that object is the allocated type. This type shall be a complete object type, but not an abstract class type or array thereof (1.8, 3.9, 10.4).
[Note: because references are not objects, references cannot be created by newexpressions. ] [Note: the typeid may be a cvqualified type, in which case the object created by the newexpression has a cvqualified type. ]
newexpression:
::opt new newplacementopt newtypeid newinitializeropt
::opt new newplacementopt ( typeid ) newinitializeropt
newplacement:
( expressionlist )
newtypeid:
typespecifierseq newdeclaratoropt
newdeclarator:
ptroperator newdeclaratoropt
directnewdeclarator
directnewdeclarator:
[ expression ]
directnewdeclarator [ constantexpression ]
newinitializer:
( expressionlistopt )
Entities created by a newexpression have dynamic storage duration (3.7.3).
[Note: the lifetime of such an entity is not necessarily restricted to the scope in which it is created. ]
If the entity is a nonarray object, the newexpression returns a pointer to the object created.
If it is an array, the newexpression returns a pointer to the initial element of the array.
-
The newtypeid in a newexpression is the longest possible sequence of newdeclarators.
[Note: this prevents ambiguities between declarator operators &, *, [], and their expression counterparts ].
[Example:
new int * i; // syntax error: parsed as (new int*) i
// not as (new int)* i
The * is the pointer declarator and not the multiplication operator. ]
-
[Note: parentheses in a newtypeid of a newexpression can have surprising effects.
[Example:
new int(*[ 10])(); // error
is illformed because the binding is
(new int) (*[ 10])(); // error
Instead, the explicitly parenthesized version of the new operator can be used to create objects of compound types (3.9.2):
new (int (*[ 10])());
allocates an array of 10 pointers to functions (taking no argument and returning int). ] ]
-
The typespecifierseq shall not contain class declarations, or enumeration declarations.
-
When the allocated object is an array (that is, the directnewdeclarator syntax is used or the newtypeid or typeid denotes an array type), the newexpression yields a pointer to the initial element (if any) of the array.
[Note: both new int and new int[10] have type int* and the type of new int[i][10] is int (*)[10]. ]
-
Every constantexpression in a directnewdeclarator shall be an integral constant expression (5.19) and evaluate to a strictly positive value.
The expression in a directnewdeclarator shall have integral type (3.9.1) with a nonnegative value.
[Example: if n is a variable of type int, then new float[n][5] is wellformed (because n is the expression of a directnewdeclarator), but new float[5][n] is illformed (because n is not a constantexpression).
If n is negative, the effect of new float[n][5] is undefined. ]
-
When the value of the expression in a directnewdeclarator is zero, the allocation function is called to allocate an array with no elements.
The pointer returned by the newexpression is nonnull.
[Note: If the library allocation function is called, the pointer returned is distinct from the pointer to any other object. ]
-
A newexpression obtains storage for the object by calling an allocation function (3.7.3.1).
If the newexpression terminates by throwing an exception, it may release storage by calling a deallocation function (3.7.3.2).
If the allocated type is a nonarray type, the allocation function's name is operator new and the deallocation function's name is operator delete. If the allocated type is an array type, the allocation function's name is operator new[] and the deallocation function's name is operator delete[].
[Note: an implementation shall provide default definitions for the global allocation functions (3.7.3, 18.4.1.1, 18.4.1.2).
A C++ program can provide alternative definitions of these functions (17.4.3.4) and/ or classspecific versions (12.5). ]
-
If the newexpression begins with a unary :: operator, the allocation function's name is looked up in the global scope.
Otherwise, if the allocated type is a class type T or array thereof, the allocation function's name is looked up in the scope of T.
If this lookup fails to find the name, or if the allocated type is not a class type, the allocation function's name is looked up in the global scope.
-
A newexpression passes the amount of space requested to the allocation function as the first argument of type std::size_t.
That argument shall be no less than the size of the object being created; it may be greater than the size of the object being created only if the object is an array.
For arrays of char and unsigned char, the difference between the result of the newexpression and the address returned by the allocation function shall be an integral multiple of the most stringent alignment requirement (3.9) of any object type whose size is no greater than the size of the array being created.
[Note: Because allocation functions are assumed to return pointers to storage that is appropriately aligned for objects of any type, this constraint on array allocation overhead permits the common idiom of allocating character arrays into which objects of other types will later be placed. ]
-
The newplacement syntax is used to supply additional arguments to an allocation function.
If used, overload resolution is performed on a function call created by assembling an argument list consisting of the amount of space requested (the first argument) and the expressions in the newplacement part of the newexpression (the second and succeeding arguments).
The first of these arguments has type size_t and the remaining arguments have the corresponding types of the expressions in the newplacement.
-
[Example:
-
new T results in a call of operator new (sizeof (T)),
-
new (2, f) T results in a call of operator new (sizeof (T), 2, f),
-
new T[5] results in a call of operator new[] (sizeof (T)* 5+ x), and
-
new (2, f) T[5] results in a call of operator new[] (sizeof (T)* 5 + y, 2, f).
Here, x and y are nonnegative unspecified values representing array allocation overhead; the result of the newexpression will be offset by this amount from the value returned by operator new[].
This overhead may be applied in all array newexpressions, including those referencing the library function operator new[] (std:: size_t, void*) and other placement allocation functions.
The amount of overhead may vary from one invocation of new to another. ]
-
[Note: unless an allocation function is declared with an empty exceptionspecification (15.4), throw(), it indicates failure to allocate storage by throwing a bad_alloc exception (clause 15, 18.4.2.1); it returns a nonnull pointer otherwise.
If the allocation function is declared with an empty exceptionspecification, throw(), it returns null to indicate failure to allocate storage and a nonnull pointer otherwise. ]
If the allocation function returns null, initialization shall not be done, the deallocation function shall not be called, and the value of the newexpression shall be null.
-
[Note: when the allocation function returns a value other than null, it must be a pointer to a block of storage in which space for the object has been reserved.
The block of storage is assumed to be appropriately aligned and of the requested size.
The address of the created object will not necessarily be the same as that of the block if the object is an array. ]
-
A newexpression that creates an object of type T initializes that object as follows:
-
If the newinitializer is omitted:
-
If T is a (possibly cvqualified) nonPOD class type (or array thereof), the object is defaultinitialized (8.5) If T is a constqualified type, the underlying class type shall have a userdeclared default constructor.
-
Otherwise, the object created has indeterminate value.
If T is a constqualified type, or a (possibly cvqualified) POD class type (or array thereof) containing (directly or indirectly) a member of constqualified type, the program is illformed;
-
If the newinitializer is of the form (), defaultinitialization shall be performed (8.5);
-
If the newinitializer is of the form (expressionlist) and T is a class type, the appropriate constructor is called, using expressionlist as the arguments (8.5);
-
If the newinitializer is of the form (expressionlist) and T is an arithmetic, enumeration, pointer, or pointertomember type and expressionlist comprises exactly one expression, then the object is initialized to the (possibly converted) value of the expression (8.5);
-
Otherwise the newexpression is illformed.
-
If the newexpression creates an object or an array of objects of class type, access and ambiguity control are done for the allocation function, the deallocation function (12.5), and the constructor (12.1).
If the new expression creates an array of objects of class type, access and ambiguity control are done for the destructor (12.4).
-
If any part of the object initialization described above 71) terminates by throwing an exception and a suitable deallocation function can be found, the deallocation function is called to free the memory in which the object was being constructed, after which the exception continues to propagate in the context of the newexpression. If no unambiguous matching deallocation function can be found, propagating the exception does not cause the object's memory to be freed.
[Note: This is appropriate when the called allocation function does not allocate memory; otherwise, it is likely to result in a memory leak. ]
-
If the newexpression begins with a unary :: operator, the deallocation function's name is looked up in the global scope.
Otherwise, if the allocated type is a class type T or an array thereof, the deallocation function's name is looked up in the scope of T. If this lookup fails to find the name, or if the allocated type is not a class type or array thereof, the deallocation function's name is looked up in the global scope.
-
A declaration of a placement deallocation function matches the declaration of a placement allocation function if it has the same number of parameters and, after parameter transformations (8.3.5), all parameter types except the first are identical.
Any nonplacement deallocation function matches a nonplacement allocation function.
If the lookup finds a single matching deallocation function, that function will be called; otherwise, no deallocation function will be called.
-
If a newexpression calls a deallocation function, it passes the value returned from the allocation function call as the first argument of type void*.
If a placement deallocation function is called, it is passed the same additional arguments as were passed to the placement allocation function, that is, the same arguments as those specified with the newplacement syntax.
If the implementation is allowed to make a copy of any argument as part of the call to the allocation function, it is allowed to make a copy (of the same original value) as part of the call to the deallocation function or to reuse the copy made as part of the call to the allocation function.
If the copy is elided in one place, it need not be elided in the other.
-
Whether the allocation function is called before evaluating the constructor arguments or after evaluating the constructor arguments but before entering the constructor is unspecified.
It is also unspecified whether the arguments to a constructor are evaluated if the allocation function returns the null pointer or exits using an exception.
5.3.5 Delete
|
[expr.delete]
|
-
The deleteexpression operator destroys a most derived object (1.8) or array created by a newexpression.
deleteexpression:
::opt delete castexpression
::opt delete [ ] castexpression
The first alternative is for nonarray objects, and the second is for arrays.
The operand shall have a pointer type, or a class type having a single conversion function (12.3.2) to a pointer type.
The result has type void.
-
If the operand has a class type, the operand is converted to a pointer type by calling the abovementioned conversion function, and the converted operand is used in place of the original operand for the remainder of this section.
In either alternative, if the value of the operand of delete is the null pointer the operation has no effect.
In the first alternative (delete object), the value of the operand of delete shall be a pointer to a nonarray object or a pointer to a subobject (1.8) representing a base class of such an object (clause 10).
If not, the behavior is undefined.
In the second alternative (delete array), the value of the operand of delete shall be the pointer value which resulted from a previous array newexpression 72).
If not, the behavior is undefined.
[Note: this means that the syntax of the deleteexpression must match the type of the object allocated by new, not the syntax of the newexpression ].
[Note: a pointer to a const type can be the operand of a deleteexpression; it is not necessary to cast away the constness (5.2.11) of the pointer expression before it is used as the operand of the deleteexpression].
-
In the first alternative (delete object), if the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand's dynamic type and the static type shall have a virtual destructor or the behavior is undefined.
In the second alternative (delete array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined 73).
-
The castexpression in a deleteexpression shall be evaluated exactly once.
If the deleteexpression calls the implementation deallocation function (3.7.3.2), and if the operand of the delete expression is not the null pointer constant, the deallocation function will deallocate the storage referenced by the pointer thus rendering the pointer invalid.
[Note: the value of a pointer that refers to deallocated storage is indeterminate. ]
-
If the object being deleted has incomplete class type at the point of deletion and the complete class has a nontrivial destructor or a deallocation function, the behavior is undefined.
-
The deleteexpression will invoke the destructor (if any) for the object or the elements of the array being deleted.
In the case of an array, the elements will be destroyed in order of decreasing address (that is, in reverse order of the completion of their constructor; see 12.6.2).
-
The deleteexpression will call a deallocation function (3.7.3.2).
-
[Note: An implementation provides default definitions of the global deallocation functions operator delete() for nonarrays (18.4.1.1) and operator delete[]() for arrays (18.4.1.2).
A C++ program can provide alternative definitions of these functions (17.4.3.4), and/or classspecific
versions (12.5). ]
When the keyword delete in a deleteexpression is preceded by the unary :: operator, the global deallocation function is used to deallocate the storage.
-
Access and ambiguity control are done for both the deallocation function and the destructor (12.4, 12.5).
5.4 Explicit type conversion (cast notation)
|
[expr.cast]
|
-
The result of the expression (T) castexpression is of type T. The result is an lvalue if T is a reference type, otherwise the result is an rvalue.
[Note: if T is a nonclass type that is cvqualified, the cvqualifiers are ignored when determining the type of the resulting rvalue; see 3.10. ]
-
An explicit type conversion can be expressed using functional notation (5.2.3), a type conversion operator (dynamic_cast, static_cast, reinterpret_cast, const_cast), or the cast notation.
castexpression:
unaryexpression
( typeid ) castexpression
-
Types shall not be defined in casts.
-
Any type conversion not mentioned below and not explicitly defined by the user (12.3) is illformed.
-
The conversions performed by
-
a const_cast (5.2.11),
-
a static_cast (5.2.9),
-
a static_cast followed by a const_cast,
-
a reinterpret_cast (5.2.10), or
-
a reinterpret_cast followed by a const_cast,
can be performed using the cast notation of explicit type conversion.
The same semantic restrictions and behaviors apply.
If a conversion can be interpreted in more than one of the ways listed above, the interpretation that appears first in the list is used, even if a cast resulting from that interpretation is illformed.
If a conversion can be interpreted in more than one way as a static_cast followed by a const_cast, the conversion is illformed. [Example :
struct A {};
struct I1 : A {};
struct I2 : A {};
struct D : I1, I2 {};
A *foo (D *p) {
return (A*) (p); // illformed static_cast interpretation
}
--end example]
-
The operand of a cast using the cast notation can be an rvalue of type "pointer to incomplete class type".
The destination type of a cast using the cast notation can be "pointer to incomplete class type".
In such cases, even if there is a inheritance relationship between the source and destination classes, whether the static_cast or reinterpret_cast interpretation is used is unspecified.
-
In addition to those conversions, the following static_cast and reinterpret_cast operations (optionally followed by a const_cast operation) may be performed using the cast notation of explicit type conversion, even if the base class type is not accessible:
-
a pointer to an object of derived class type or an lvalue of derived class type may be explicitly converted to a pointer or reference to an unambiguous base class type, respectively;
-
a pointer to member of derived class type may be explicitly converted to a pointer to member of an unambiguous nonvirtual base class type;
-
a pointer to an object of nonvirtual base class type, an lvalue of nonvirtual base class type, or a pointer to member of nonvirtual base class type may be explicitly converted to a pointer, a reference, or a pointer to member of a derived class type, respectively.
5.5 Pointertomember operators
|
[expr.mptr.oper]
|
-
The pointertomember operators >* and .* group lefttoright.
pmexpression:
castexpression
pmexpression .* castexpression
pmexpression >* castexpression
-
The binary operator .* binds its second operand, which shall be of type "pointer to member of T" (where T is a completelydefined class type) to its first operand, which shall be of class T or of a class of which T is an unambiguous and accessible base class.
The result is an object or a function of the type specified by the second operand.
-
The binary operator >* binds its second operand, which shall be of type "pointer to member of T" (where T is a completelydefined class type) to its first operand, which shall be of type "pointer to T" or "pointer to a class of which T is an unambiguous and accessible base class." The result is an object or a function of the type specified by the second operand.
-
If the dynamic type of the object does not contain the member to which the pointer refers, the behavior is undefined.
-
The restrictions on cvqualification, and the manner in which the cvqualifiers of the operands are combined to produce the cvqualifiers of the result, are the same as the rules for E1.E2 given in 5.2.5.
[Note: it is not possible to use a pointer to member that refers to a mutable member to modify a const class object.
For example,
struct S {
mutable int i;
};
const S cs;
int S::*pm = &S::i;
// pm refers to mutable member S::i
cs.*pm = 88;
// illformed: cs is a const object
]
-
If the result of .* or >* is a function, then that result can be used only as the operand for the function call operator ().
[Example :
(ptr_to_obj>* ptr_to_mfct) (10);
calls the member function denoted by ptr_to_mfct for the object pointed to by ptr_to_obj ].
The result of a .* expression is an lvalue only if its first operand is an lvalue and its second operand is a pointer to data member.
The result of an >* expression is an lvalue only if its second operand is a pointer to data member.
If the second operand is the null pointer to member value (4.11), the behavior is undefined.
5.6 Multiplicative operators
|
[expr.mul]
|
-
The multiplicative operators *, /, and % group lefttoright.
multiplicativeexpression:
pmexpression
multiplicativeexpression * pmexpression
multiplicativeexpression / pmexpression
multiplicativeexpression % pmexpression
-
The operands of * and / shall have arithmetic or enumeration type; the operands of % shall have integral or enumeration type.
The usual arithmetic conversions are performed on the operands and determine the type of the result.
-
The binary * operator indicates multiplication.
-
The binary / operator yields the quotient, and the binary % operator yields the remainder from the division of the first expression by the second.
If the second operand of / or % is zero the behavior is undefined; otherwise (a/ b)* b + a% b is equal to a.
If both operands are nonnegative then the remainder is nonnegative; if not, the sign of the remainder is implementationdefined 74).
5.7 Additive operators
|
[expr.add]
|
-
The additive operators + and group lefttoright.
The usual arithmetic conversions are performed for operands of arithmetic or enumeration type.
additiveexpression:
multiplicativeexpression
additiveexpression + multiplicativeexpression
additiveexpression multiplicativeexpression
For addition, either both operands shall have arithmetic or enumeration type, or one operand shall be a pointer to a completely defined object type and the other shall have integral or enumeration type.
-
For subtraction, one of the following shall hold:
-
both operands have arithmetic or enumeration type; or
-
both operands are pointers to cvqualified or cvunqualified versions of the same completely defined object type; or
-
the left operand is a pointer to a completely defined object type and the right operand has integral or enumeration type.
-
The result of the binary + operator is the sum of the operands.
The result of the binary operator is the difference resulting from the subtraction of the second operand from the first.
-
For the purposes of these operators, a pointer to a nonarray object behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.
-
When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand.
If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integral expression.
In other words, if the expression P points to the ith element of an array object, the expressions (P)+ N (equivalently, N + (P)) and (P)N (where N has the value n) point to, respectively, the i+nth and i± nth elements of the array object, provided they exist.
Moreover, if the expression P points to the last element of an array object, the expression (P) + 1 points one past the last element of the array object, and if the expression Q points one past the last element of an array object, the expression (Q)1 points to the last element of the array object.
If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.
-
When two pointers to elements of the same array object are subtracted, the result is the difference of the subscripts of the two array elements.
The type of the result is an implementationdefined signed integral type; this type shall be the same type that is defined as ptrdiff_t in the <cstddef> header (18.1).
As with any other arithmetic overflow, if the result does not fit in the space provided, the behavior is undefined.
In other words, if the expressions P and Q point to, respectively, the ith and jth elements of an array object, the expression (P)( Q) has the value i± j provided the value fits in an object of type ptrdiff_t.
Moreover, if the expression P points either to an element of an array object or one past the last element of an array object, and the expression Q points to the last element of the same array object, the expression ((Q) + 1) (P) has the same value as ((Q) (P)) + 1 and as ((P)((Q) + 1)), and has the value zero if the expression P points one past the last element of the array object, even though the expression (Q) + 1 does not point to an element of the array object.
Unless both pointers point to elements of the same array object, or one past the last element of the array object, the behavior is undefined 75).
-
When viewed in this way, an implementation need only provide one extra byte (which may overlap another object in the program) just after the end of the object in order to satisfy the "one past the last element" requirements.
-
If the value 0 is added to or subtracted from a pointer value, the result compares equal to the original pointer value.
If two pointers point to the same object or function or both point one past the end of the same array or both are null, and the two pointers are subtracted, the result compares equal to the value 0 converted to the type ptrdiff_t
5.8 Shift operators
|
[expr.shift]
|
-
The shift operators << and >> group lefttoright.
shiftexpression:
additiveexpression
shiftexpression << additiveexpression
shiftexpression >> additiveexpression
The operands shall be of integral or enumeration type and integral promotions are performed.
The type of the result is that of the promoted left operand.
The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand.
-
The value of E1 << E2 is E1 (interpreted as a bit pattern) leftshifted E2 bit positions; vacated bits are zerofilled.
If E1 has an unsigned type, the value of the result is E1 multiplied by the quantity 2 raised to the power E2, reduced modulo ULONG_MAX + 1 if E1 has type unsigned long, UINT_MAX + 1 otherwise.
[Note: the constants ULONG_MAX and UINT_MAX are defined in the header <climits>).
]
-
The value of E1 >> E2 is E1 rightshifted E2 bit positions.
If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 divided by the quantity 2 raised to the power E2.
If E1 has a signed type and a negative value, the resulting value is implementationdefined.
5.9 Relational operators
|
[expr.rel]
|
-
The relational operators group lefttoright.
[Example : a < b < c means (a < b) < c and not (a < b)&&( b< c). ]
relationalexpression:
shiftexpression
relationalexpression < shiftexpression
relationalexpression > shiftexpression
relationalexpression <= shiftexpression
relationalexpression >= shiftexpression
The operands shall have arithmetic, enumeration or pointer type.
The operators < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to) all yield false or true. The type of the result is bool.
-
The usual arithmetic conversions are performed on operands of arithmetic or enumeration type.
Pointer conversions (4.10) and qualification conversions (4.4) are performed on pointer operands (or on a pointer operand and a null pointer constant) to bring them to their composite pointer type.
If one operand is a null pointer constant, the composite pointer type is the type of the other operand.
Otherwise, if one of the operands has type "pointer to cv1 void", then the other has type "pointer to cv2 T" and the composite pointer type is "pointer to cv12 void", where cv12 is the union of cv1 and cv2.
Otherwise, the composite pointer type is a pointer type similar (4.4) to the type of one of the operands, with a cvqualification signature (4.4) that is the union of the cvqualification signatures of the operand types.
[Note : this implies that any pointer can be compared to a null pointer constant and that any object pointer can be compared to a pointer to (possibly cvqualified) void ].
[Example :
void *p;
const int *q;
int ** pi;
const int *const *pci;
void ct()
{
p <= q;
// Both converted to const void * before comparison
pi <= pci;
// Both converted to const int *const * before comparison
}
--end example] Pointers to objects or functions of the same type (after pointer conversions) can be compared, with a result defined as follows:
-
If two pointers p and q of the same type point to the same object or function, or both point one past the end of the same array, or are both null, then p<= q and p>= q both yield true and p< q and p> q both yield false.
-
If two pointers p and q of the same type point to different objects that are not members of the same object or elements of the same array or to different functions, or if only one of them is null, the results of p< q, p> q, p<= q, and p>= q are unspecified.
-
If two pointers point to nonstatic data members of the same object, or to subobjects or array elements of such members, recursively, the pointer to the later declared member compares greater provided the two members are not separated by an accessspecifier label (11.1) and provided their class is not a union.
-
If two pointers point to nonstatic data members of the same object separated by an accessspecifier label (11.1) the result is unspecified.
-
If two pointers point to data members of the same union object, they compare equal (after conversion to void*, if necessary).
If two pointers point to elements of the same array or one beyond the end of the array, the pointer to the object with the higher subscript compares higher.
-
Other pointer comparisons are unspecified.
5.10 Equality operators
|
[expr.eq]
|
equalityexpression:
relationalexpression
equalityexpression == relationalexpression
equalityexpression != relationalexpression
-
The == (equal to) and the != (not equal to) operators have the same semantic restrictions, conversions, and result type as the relational operators except for their lower precedence and truthvalue result.
[Note : a < b == c < d is true whenever a < b and c < d have the same truthvalue.
] Pointers to objects or functions of the same type (after pointer conversions) can be compared for equality.
Two pointers of the same type compare equal if and only if they are both null, both point to the same object or function, or both point one past the end of the same array.
-
In addition, pointers to members can be compared, or a pointer to member and a null pointer constant.
Pointer to member conversions (4.11) and qualification conversions (4.4) are performed to bring them to a common type.
If one operand is a null pointer constant, the common type is the type of the other operand.
Otherwise, the common type is a pointer to member type similar (4.4) to the type of one of the operands, with a cvqualification signature (4.4) that is the union of the cvqualification signatures of the operand types.
[Note : this implies that any pointer to member can be compared to a null pointer constant. ]
If both operands are null, they compare equal.
Otherwise if only one is null, they compare unequal.
Otherwise if either is a pointer to a virtual member function, the result is unspecified.
Otherwise they compare equal if and only if they would refer to the same member of the same most derived object (1.8) or the same subobject if they were dereferenced with a hypothetical object of the associated class type.
[Example :
struct B {
int f();
};
struct L : B { };
struct R : B { };
struct D : L, R { };
int (B::* pb)() = &B:: f;
int (L::* pl)() = pb;
int (R::* pr)() = pb;
int (D::* pdl)() = pl;
int (D::* pdr)() = pr;
bool x = (pdl == pdr); // false
Ðend example]
5.11 Bitwise AND operator
|
[expr.bit.and]
|
-
andexpression:
equalityexpression
andexpression & equalityexpression
-
The usual arithmetic conversions are performed; the result is the bitwise AND function of the operands.
The operator applies only to integral or enumeration operands.
5.12 Bitwise exclusive OR operator
|
[expr.xor]
|
exclusiveorexpression:
andexpression
exclusiveorexpression ^ andexpression
-
The usual arithmetic conversions are performed; the result is the bitwise exclusive OR function of the operands.
The operator applies only to integral or enumeration operands.
5.13 Bitwise inclusive OR operator
|
[expr.or]
|
inclusiveorexpression:
exclusiveorexpression
inclusiveorexpression | exclusiveorexpression
-
The usual arithmetic conversions are performed; the result is the bitwise inclusive OR function of its operands.
The operator applies only to integral or enumeration operands.
5.14 Logical AND operator
|
[expr.log.and]
|
logicalandexpression:
inclusiveorexpression
logicalandexpression && inclusiveorexpression
-
The && operator groups lefttoright.
The operands are both implicitly converted to type bool (clause 4).
The result is true if both operands are true and false otherwise.
Unlike &, && guarantees lefttoright evaluation: the second operand is not evaluated if the first operand is false.
-
The result is a bool. All side effects of the first expression except for destruction of temporaries (12.2) happen before the second expression is evaluated.
5.15 Logical OR operator
|
[expr.log.or]
|
logicalorexpression:
logicalandexpression
logicalorexpression || logicalandexpression
-
The || operator groups lefttoright.
The operands are both implicitly converted to bool (clause 4).
It returns true if either of its operands is true, and false otherwise.
Unlike |, || guarantees lefttoright evaluation; moreover, the second operand is not evaluated if the first operand evaluates to true.
-
The result is a bool. All side effects of the first expression except for destruction of temporaries (12.2) happen before the second expression is evaluated.
5.16 Conditional operator
|
[expr.cond]
|
conditionalexpression:
logicalorexpression
logicalorexpression ? expression : assignmentexpression
-
Conditional expressions group righttoleft.
The first expression is implicitly converted to bool (clause 4).
It is evaluated and if it is true, the result of the conditional expression is the value of the second expression, otherwise that of the third expression.
All side effects of the first expression except for destruction of temporaries (12.2) happen before the second or third expression is evaluated.
Only one of the second and third expressions is evaluated.
-
If either the second or the third operand has type (possibly cvqualified) void, then the lvaluetorvalue (4.1), arraytopointer (4.2), and functiontopointer (4.3) standard conversions are performed on the second and third operands, and one of the following shall hold:
-
The second or the third operand (but not both) is a throwexpression (15.1); the result is of the type of the other and is an rvalue.
-
Both the second and the third operands have type void; the result is of type void and is an rvalue.
[Note : this includes the case where both operands are throwexpressions. ]
-
Otherwise, if the second and third operand have different types, and either has (possibly cvqualified) class type, an attempt is made to convert each of those operands to the type of the other.
The process for determining whether an operand expression E1 of type T1 can be converted to match an operand expression E2 of type T2 is defined as follows:
-
If E2 is an lvalue: E1 can be converted to match E2 if E1 can be implicitly converted (clause 4) to the type "reference to T2", subject to the constraint that in the conversion the reference must bind directly (8.5.3) to E1.
-
If E2 is an rvalue, or if the conversion above cannot be done:
-
if E1 and E2 have class type, and the underlying class types are the same or one is a base class of the other: E1 can be converted to match E2 if the class of T2 is the same type as, or a base class of, the class of T1, and the cvqualification of T2 is the same cvqualification as, or a greater cvqualification than, the cvqualification of T1.
-
If the conversion is applied, E1 is changed to an rvalue of type T2 that still refers to the original source class object (or the appropriate subobject thereof).
[Note : that is, no copy is made. ]
-
Otherwise (i. e., if E1 or E2 has a nonclass type, or
if they both have class types but the underlying
classes are not either the same or one a base class of the other): E1 can be converted to match E2 if E1 can be implicitly converted to the type that expression E2 would have if E2 were converted to an rvalue (or the type it has, if E2 is an rvalue).
Using this process, it is determined whether the second operand can be converted to match the third operand, and whether the third operand can be converted to match the second operand.
If both can be converted, or one can be converted but the conversion is ambiguous, the program is illformed.
If neither can be converted, the operands are left unchanged and further checking is performed as described below.
If exactly one conversion is possible, that conversion is applied to the chosen operand and the converted operand is used in place of the original operand for the remainder of this section.
-
If the second and third operands are lvalues and have the same type, the result is of that type and is an lvalue.
-
Otherwise, the result is an rvalue.
If the second and third operand do not have the same type, and either has (possibly cvqualified) class type, overload resolution is used to determine the conversions (if any) to be applied to the operands (13.3.1.2, 13.6).
If the overload resolution fails, the program is illformed.
Otherwise, the conversions thus determined are applied, and the converted operands are used in place of the original operands for the remainder of this section.
-
Lvaluetorvalue (4.1), arraytopointer (4.2), and functiontopointer (4.3) standard conversions are performed on the second and third operands.
After those conversions, one of the following shall hold:
-
The second and third operands have the same type; the result is of that type.
-
The second and third operands have arithmetic or enumeration type; the usual arithmetic conversions are performed to bring them to a common type, and the result is of that type.
-
The second and third operands have pointer type, or one has pointer type and the other is a null pointer constant; pointer conversions (4.10) and qualification conversions (4.4) are performed to bring them to their composite pointer type (5.9).
The result is of the composite pointer type.
-
The second and third operands have pointer to member type, or one has pointer to member type and the other is a null pointer constant; pointer to member conversions (4.11) and qualification conversions (4.4) are performed to bring them to a common type, whose cvqualification shall match the cvqualification of either the second or the third operand.
The result is of the common type.
5.17 Assignment operators
|
[expr.ass]
|
-
There are several assignment operators, all of which group righttoleft.
All require a modifiable lvalue as their left operand, and the type of an assignment expression is that of its left operand.
The result of the assignment operation is the value stored in the left operand after the assignment has taken place; the result is an lvalue.
assignmentexpression:
conditionalexpression
logicalorexpression assignmentoperator assignmentexpression
throwexpression
assignmentoperator: one of
= *= /= %= += =>>= <<= &= ^= |=
-
In simple assignment (=), the value of the expression replaces that of the object referred to by the left operand.
-
If the left operand is not of class type, the expression is implicitly converted (clause 4) to the cvunqualified type of the left operand.
-
If the left operand is of class type, the class shall be complete.
Assignment to objects of a class is defined by the copy assignment operator (12.8, 13.5.3).
-
[Note : For class objects, assignment is not in general the same as initialization (8.5, 12.1, 12.6, 12.8). ]
-
When the left operand of an assignment operator denotes a reference to T, the operation assigns to the object of type T denoted by the reference.
-
The behavior of an expression of the form E1 op= E2 is equivalent to E1 = E1 op E2 except that E1 is evaluated only once.
In += and =, E1 shall either have arithmetic type or be a pointer to a possibly cvqualified completely defined object type.
In all other cases, E1 shall have arithmetic type.
-
If the value being stored in an object is accessed from another object that overlaps in any way the storage of the first object, then the overlap shall be exact and the two objects shall have the same type, otherwise the behavior is undefined.
5.18 Comma operator
|
[expr.comma]
|
-
The comma operator groups lefttoright.
expression:
assignmentexpression
expression , assignmentexpression
A pair of expressions separated by a comma is evaluated lefttoright and the value of the left expression is discarded.
The lvaluetorvalue (4.1), arraytopointer (4.2), and functiontopointer (4.3) standard conversions are not applied to the left expression.
All side effects (1.9) of the left expression, except for the destruction of temporaries (12.2), are performed before the evaluation of the right expression.
The type and value of the result are the type and value of the right operand; the result is an lvalue if its right operand is.
-
In contexts where comma is given a special meaning, [Example : in lists of arguments to functions (5.2.2) and lists of initializers (8.5) ] the comma operator as described in clause 5 can appear only in parentheses.
[Example :
f (a, (t = 3, t + 2), c);
has three arguments, the second of which has the value 5. ]
5.19 Constant expressions
|
[expr.const]
|
-
In several places, C++ requires expressions that evaluate to an integral or enumeration constant: as array bounds (8.3.4, 5.3.4), as case expressions (6.4.2), as bitfield lengths (9.6), as enumerator initializers (7.2), as static member initializers (9.4.2), and as integral or enumeration nontype template arguments (14.3).
constantexpression:
conditionalexpression
An integral constantexpression can involve only literals (2.13), enumerators, const variables or static data members of integral or enumeration types initialized with constant expressions (8.5), nontype template parameters of integral or enumeration types, and sizeof expressions.
Floating literals (2.13.3) can appear only if they are cast to integral or enumeration types.
Only type conversions to integral or enumeration types can be used.
In particular, except in sizeof expressions, functions, class objects, pointers, or references shall not be used, and assignment, increment, decrement, functioncall, or comma operators shall not be used.
-
Other expressions are considered constantexpressions only for the purpose of nonlocal static object initialization (3.6.2).
Such constant expressions shall evaluate to one of the following:
-
a null pointer value (4.10),
-
a null member pointer value (4.11),
-
an arithmetic constant expression,
-
an address constant expression,
-
a reference constant expression,
-
an address constant expression for a complete object type, plus or minus an integral constant expression, or
-
a pointer to member constant expression.
-
An arithmetic constant expression shall have arithmetic or enumeration type and shall only have operands that are integer literals (2.13.1), floating literals (2.13.3), enumerators, character literals (2.13.2) and sizeof expressions (5.3.3).
Cast operators in an arithmetic constant expression shall only convert arithmetic or enumeration types to arithmetic or enumeration types, except as part of an operand to the sizeof operator.
-
An address constant expression is a pointer to an lvalue designating an object of static storage duration, a string literal (2.13.4), or a function.
The pointer shall be created explicitly, using the unary & operator, or implicitly using a nontype template parameter of pointer type, or using an expression of array (4.2) or function (4.3) type.
The subscripting operator [] and the class member access . and > operators, the & and * unary operators, and pointer casts (except dynamic_casts, 5.2.7) can be used in the creation of an address constant expression, but the value of an object shall not be accessed by the use of these operators.
If the subscripting operator is used, one of its operands shall be an integral constant expression.
An expression that designates the address of a member or base class of a nonPOD class object (clause 9) is not an address constant expression (12.7).
Function calls shall not be used in an address constant expression, even if the function is inline and has a reference return type.
-
A reference constant expression is an lvalue designating an object of static storage duration, a nontype template parameter of reference type, or a function.
The subscripting operator [], the class memer access. and > operators, the & and * unary operators, and reference casts (except those invoking usedefined conversion functions (12.3.2) and except dynamic_casts (5.2.7)) can be used in the creation of reference constant expression, but the value of an object shall not be accessed by the use of these operators.
If the subscripting operator is used, one of its operands shall be an integral constant expression.
An lvalue expression that designates a member or base class of a nonPOD class object (clause 9) is not a reference constant expression (12.7).
Function calls shall not be used in a reference constant expression, even if the function is inline and has a reference return type.
-
A pointer to member constant expression shall be created using the unary & operator applied to a qualifiedid operand (5.3.1), optionally preceded by a pointer to member cast (5.2.9).
69) sizeof (bool)is not required to be 1.
70) The actual size of a base class subobject may be less than the result of applying sizeofto the subobject, due to virtual base classes and less strict padding requirements on base class subobjects.
71) This may include evaluating a newinitializer and/or calling a constructor.
72) For nonzerolength arrays, this is the same as a pointer to the first element of the array created by that newexpression. Zerolength arrays do not have a first element.
73) This implies that an object cannot be deleted using a pointer of type void*because there are no objects of type void.
74) According to work underway toward the revision of ISO C, the preferred algorithm for integer division follows the rules defined in the ISO Fortran standard, ISO/ IEC 1539: 1991, in which the quotient is always rounded toward zero.
75) Another way to approach pointer arithmetic is first to convert the pointer(s) to character pointer(s): In this scheme the integral value of the expression added to or subtracted from the converted pointer is first multiplied by the size of the object originally pointed to, and the resulting pointer is converted back to the original type.
For pointer subtraction, the result of the difference between the character pointers is similarly divided by the size of the object originally pointed to.
When viewed in this way, an implementation need only provide one extra byte (which might overlap another object in the program) just after the end of the object in order to satisfy the "one past the last element" requirements.