The const Modifier for Reference Arguments

As you may recall from our discussion of types of arguments in earlier chapters, when you call a function using a value argument, the argument that you supply in the calling function isn't the one that the called function receives. Instead, a copy is made of the calling function's argument, and the called function works on the copy. While this is fine most of the time, in this case it won't work properly for reasons that will be apparent shortly; instead, we have to use a reference argument. As we saw in the discussion of reference arguments in Chapter 6, such an argument is not a copy of the caller's argument, but another name for the actual argument provided by the caller. This has a number of consequences. First, it's often more efficient than a "normal" argument, because the usual processing time needed to make a copy for the called function isn't required. Second, any changes made to the reference argument change the caller's argument as well. The use of this mechanism should be limited to those cases where it is really necessary, since it can confuse the readers of the calling function. There's no way to tell just by looking at the calling function that some of its variables can be changed by calling another function.

In this case, however, we have no intention of changing the input argument. All we want to do is to copy its length and data into the output string, the one for which operator = was called. Therefore, we tell the compiler, by using the const modifier, that we aren't going to change the input argument. This removes the drawback of non-const reference arguments: that they can change variables in the calling function with no indication of that possibility in the calling function. Therefore, using const reference arguments is quite a useful and safe way to reduce the number of time-consuming copying operations needed to make function calls.

However in this case, the use of a const reference argument is more than just efficient. As we'll see in the discussion starting under the heading “The Compiler Generates a Temporary Variable” on page 474 in Chapter 8, such an argument allows us to assign a C string (i.e., bytes pointed to by a char*) to one of our string variables without having to write a special operator = for that purpose.[14]

[14] Now I can tell you what the real type of a C string literal is. Before the adoption of the C++ standard, the type actually was char*, as I said on page 410. Now, however, it's actually a const char*, because you really shouldn't change literal values. The reason this difference doesn't matter is that C++ will automatically convert the type of a C string literal to char* whenever necessary, to preserve the behavior of prestandard programs. This shouldn't affect us, because we know better than to change the value of a C string literal.

You might be surprised to hear that Susan didn't have too much trouble accepting all this stuff about const reference arguments. Obviously her resistance to new ideas was weakening by this point.

Susan: OK, so the reference operator just renames the argument and doesn't make a copy of it; that is why it is important to promise not to change it?

Steve: Right. A non-const reference argument can be changed in the called function, because unlike a "regular" (i.e., value) argument, which is really a copy of the calling function's variable, a reference argument is just another name for the caller's variable. Therefore, if we change the reference argument we're really changing the caller's variable, which is generally not a good idea.

Susan: OK. But in this case since we are going to want to change the meaning of = in all strings it is OK?

Steve: Not quite. Every time we define an operator we're changing the meaning of that operator for all objects of that class. The question is whether we're intending to change the value of the caller's variable that is referred to by the reference argument. If we are, then we can't use const to qualify the reference; if not, we can use const. Does that answer your question?

Susan: Well, yes and no. I think I have it now: When you write that code it is for that class only and won't affect other classes that you may have written, because it is contained within that particular class code. Right?

Steve: Correct.

Susan: So we don't want to change the input argument because we are basically defining a new = for this class, right?

Steve: Right. The input argument is where we get the data to copy to the string we're assigning to. We don't want to change the input argument, just the string we're assigning to.

Back to the discussion of the function declaration, we now have enough information to decode the function declaration

string& string::operator = (const string& Str)

as illustrated in Figure 7.13.

Figure 7.13. The declaration of operator = for the string class


Putting it all together, we're defining a function belonging to class string that returns a reference to a string. This function implements operator = and takes an argument named Str that's a constant reference to a string. That is, the argument Str is another name for the string passed to us by the caller, not a copy of the caller's string. Furthermore, we're vowing not to use this argument to change the caller's variable.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset