May 20th Wednesday (五月 二十日 水曜日)

来源:互联网 发布:人工智能之父英文介绍 编辑:程序博客网 时间:2024/05/18 00:51

Temporary Variables, Reference Arguments, and const

  C++ can generate a temporary variable if the actual argument doesn't match a reference argument. Currently,
C++ permits this only if the argument is a const reference, but this is a new restriction. Let's look at the cases
in which C++ does generate temporary variables and see why the restriction to a const reference makes sense.

  First, when is a temporary variable created? Provided that the reference parameter is a const, the compiler
generates a temporary variable in two kinds of situations:

* The actual argument is the correct type, but isn't an Lvalue
* The actual argument is of the wrong type, but of a type that can be converted to the correct type

void swapr(int & a, int & b)  // use references
{
    int temp;

    temp = a;      // use a, b for values of variables
    a = b;
    b = temp;
}

double refcube(const double &ra)
{
     return ra * ra * ra;
}

Now consider the following code:

double side = 3.0;
double * pd = &side;
double & rd = side;
long edge = 5L;
double lens[4] = { 2.0, 5.0, 10.0, 12.0} ;
double c1 = refcube(side);          // ra is side
double c2 = refcube(lens[2]);       // ra is lens[2]
double c3 = refcube(rd);            // ra is rd is side
double c4 = refcube(*pd);           // ra is *pd is side
double c5 = refcube(edge);          // ra is temporary variable
double c6 = refcube(7.0);           // ra is temporary variable
double c7 = refcube(side + 10.0);   // ra is temporary variable

  The arguments side, lens[2], rd, and *pd are type double data objects with names, so it is possible to
generate a reference for them, and no temporary variables are needed. (Recall that an element of an array
behaves like a variable of the same type as the element.) But edge, although a variable, is of the wrong type.
A reference to a double can't refer to a long. The arguments 7.0 and side + 10.0, on the other hand, are
the right type, but are not named data objects. In each of these cases, the compiler generates a temporary,
anonymous variable and makes ra refer to it. These temporary variables last for the duration of the function
call, but then the compiler is free to dump them.

  What would happen if we did the following under the freer rules of early C++?

long a = 3, b = 5;
swapr(a, b);

  Here there is a type mismatch, so the compiler would create two temporary int variables, initialize them to 3 and 5,
and then swap the contents of the temporary variables, leaving a and b unaltered.

  In short, if the intent of a function with reference arguments is to modify variables passed as arguments, situations
that create temporary variables thwart that purpose. The solution is to prohibit creating temporary variables in these
situations, and that is what the C++ standard now does. (However, some compilers still, by default, issue warnings
instead of error messages, so if you do see a warning about temporary variables, don't ignore it.)

  Now think about the refcube() function. Its intent is merely to use passed values, not to modify them, so temporary
variables cause no harm and make the function more general in the sorts of arguments that it can handle. Therefore, if
the declaration states that a reference is const, C++ generates temporary variables when necessary. In essence, a C++
function with a const reference formal argument and a nonmatching actual argument mimics the traditional passing by value
behavior, guaranteeing that the original data is unaltered and using a temporary variable to hold the value.

Remember

  If a function call argument isn't an Lvalue or does not match the type of the corresponding const reference parameter,
C++ creates an anonymous variable of the correct type, assigns the value of the function call argument to the anonymous
variable, and has the parameter refer to that variable.

Use const When You Can

  There are three strong reasons to declare reference arguments as references to constant data:

  * Using const protects you against programming errors that inadvertently alter data.
  * Using const allows a function to process both const and non-const actual arguments, while a function omitting const in
   the prototype only can accept non-const data.
  * Using a const reference allows the function to generate and use a temporary variable appropriately.

  You should declare formal reference arguments as const whenever it's appropriate to do so.

  Typically, the reference refers to a reference passed to the function in the first place, so the calling function actually
winds up directly accessing one of its own variables.

Remember

  A function that returns a reference is actually an alias for the referred-to variable.

  You can assign a value (including a structure or a class object) to a C++ function only if the function returns a reference
to a variable or, more generally, to a data object. In that case, the value is assigned to the referred-to variable or data object.

  There are two main reasons for using reference arguments:

  * To allow you to alter a data object in the calling function
  * To speed up a program by passing a reference instead of an entire data object

  The second reason is most important for larger data objects, such as structures and class objects.

原创粉丝点击