const
ObjectThe preceding definition of Vector::operator+()
has a bizarre property. The intended use is this:
net = force1 + force2; // 1: three Vector objects
However, the definition also allows you to use the following:
force1 + force2 = net; // 2: dyslectic programming
cout << (force1 + force2 = net).magval() << endl; // 3: demented programming
Three questions immediately arise. Why would anyone write such statements? Why are they possible? What do they do?
First, there is no sensible reason for writing such code, but not all code is written for sensible reasons. People, even programmers, make mistakes. For instance, if the comparison operator==()
were defined for the Vector
class, you might mistakenly type
if (force1 + force2 = net)
instead of this:
if (force1 + force2 == net)
Also programmers tend to be ingenious, and this can lead to ingeniously adventurous mistakes.
Second, this code is possible because the copy constructor constructs a temporary object to represent the return value. So in the preceding code, the expression force1 + force2
stands for that temporary object. In Statement 1, the temporary object is assigned to net
. In Statements 2 and 3, net
is assigned to the temporary object.
Third, the temporary object is used and then discarded. For instance, in Statement 2, the program computes the sum of force1
and force2
, copies the answer into the temporary return object, overwrites the contents with the contents of net
, and then discards the temporary object. The original vectors are all left unchanged. In Statement 3, the magnitude of the temporary object is displayed before the object is deleted.
If you are concerned about the potential for misuse and abuse created by this behavior, you have a simple recourse: Declare the return type as a const
object. For instance, if Vector::operator+()
is declared to have return type const Vector
, then Statement 1 is still allowed but Statements 2 and 3 become invalid.
In summary, if a method or function returns a local object, it should return an object, not a reference. In this example, the program uses the copy constructor to generate the returned object. If a method or function returns an object of a class for which there is no public copy constructor, such as the ostream
class, it must return a reference to an object. Finally, some methods and functions, such as the overloaded assignment operator, can return either an object or a reference to an object. In this example, the reference is preferred for reasons of efficiency.
C++ programs often use pointers to objects, so let’s get in a bit of practice. Listing 12.6 uses array index values to keep track of the shortest string and of the first string alphabetically. Another approach is to use pointers to point to the current leaders in these categories. Listing 12.7 implements this approach, using two pointers to String
. Initially, the shortest
pointer points to the first object in the array. Each time the program finds an object with a shorter string, it resets shortest
to point to that object. Similarly, a first
pointer tracks the alphabetically earliest string. Note that these two pointers do not create new objects; they merely point to existing objects. Hence they don’t require using new
to allocate additional memory.
For variety, the program in Listing 12.7 uses a pointer that does keep track of a new object:
String * favorite = new String(sayings[choice]);
Here the pointer favorite
provides the only access to the nameless object created by new
. This particular syntax means to initialize the new String
object by using the object sayings[choice]
. That invokes the copy constructor because the argument type for the copy constructor (const String &
) matches the initialization value (sayings[choice]
). The program uses srand()
, rand()
, and time()
to select a value for choice at random.
// sayings2.cpp -- using pointers to objects
// compile with string1.cpp
#include <iostream>
#include <cstdlib> // (or stdlib.h) for rand(), srand()
#include <ctime> // (or time.h) for time()
#include "string1.h"
const int ArSize = 10;
const int MaxLen = 81;
int main()
{
using namespace std;
String name;
cout <<"Hi, what's your name?
>> ";
cin >> name;
cout << name << ", please enter up to " << ArSize
<< " short sayings <empty line to quit>:
";
String sayings[ArSize];
char temp[MaxLen]; // temporary string storage
int i;
for (i = 0; i < ArSize; i++)
{
cout << i+1 << ": ";
cin.get(temp, MaxLen);
while (cin && cin.get() != '
')
continue;
if (!cin || temp[0] == ' ') // empty line?
break; // i not incremented
else
sayings[i] = temp; // overloaded assignment
}
int total = i; // total # of lines read
if (total > 0)
{
cout << "Here are your sayings:
";
for (i = 0; i < total; i++)
cout << sayings[i] << "
";
// use pointers to keep track of shortest, first strings
String * shortest = &sayings[0]; // initialize to first object
String * first = &sayings[0];
for (i = 1; i < total; i++)
{
if (sayings[i].length() < shortest->length())
shortest = &sayings[i];
if (sayings[i] < *first) // compare values
first = &sayings[i]; // assign address
}
cout << "Shortest saying:
" << * shortest << endl;
cout << "First alphabetically:
" << * first << endl;
srand(time(0));
int choice = rand() % total; // pick index at random
// use new to create, initialize new String object
String * favorite = new String(sayings[choice]);
cout << "My favorite saying:
" << *favorite << endl;
delete favorite;
}
else
cout << "Not much to say, eh?
";
cout << "Bye.
";
return 0;
}
Here’s a sample run of the program in Listing 12.7:
Hi, what's your name?
>> Kirt Rood
Kirt Rood, please enter up to 10 short sayings <empty line to quit>:
1: a friend in need is a friend indeed
2: neither a borrower nor a lender be
3: a stitch in time saves nine
4: a niche in time saves stine
5: it takes a crook to catch a crook
6: cold hands, warm heart
7:
Here are your sayings:
a friend in need is a friend indeed
neither a borrower nor a lender be
a stitch in time saves nine
a niche in time saves stine
it takes a crook to catch a crook
cold hands, warm heart
Shortest saying:
cold hands, warm heart
First alphabetically:
a friend in need is a friend indeed
My favorite saying:
a stitch in time saves nine
Bye
Because the program selects the favorite saying randomly, different runs of the program will show different choices, even for identical input.
18.216.151.164