If you apply this operator to a reference, it returns the address of the referenced object.. 䊐 Read-Only References A reference that addresses a constant object must be a constant itself
Trang 1S O L U T I O N S 219
if( word1.size() > 1)
{
cout << "\nEnter the password once more: ";
cin >> setw(20) >> word2;
if( word1 == word2) // Password confirmed?
{ // Yes!
secret = word1;
return true;
}
}
return false; // No new password
}
//
-// Password.cpp
// Testing the functions getPassword() and
// changePassword()
//
// After entering the password correctly (max three
// attempts within 60 seconds), the user can change it
//
-#include <iostream>
#include <iomanip>
#include <string>
#include <cctype>
using namespace std;
bool getPassword(void); // Read a password
bool changePassword(void); // Change a password
// Inline functions:
inline void cls() { cout << "\033[2J"; }
inline void go_on()
{
cout << "\n\nGo on with return! ";
cin.sync(); cin.clear(); // Only new input
while( cin.get() != '\n')
;
}
inline char getYesOrNo() // Read character Y or N
{
char c = 0;
cin.sync(); cin.clear(); // Just new input
do
{
cin.get(c);
c = toupper(c); // Permitting lower case letters also }
while( c != 'Y' && c != 'N');
return c;
}
Trang 2220 C H A P T E R 1 1 S T 0 R A G E C L A S S E S A N D N A M E S P A C E S
static string header =
"\n\n **** Test password handling ****\n\n";
static string menu =
"\n\n B = Booking "
"\n\n E = End of program"
"\n\n Your choice: ";
int main() {
char choice = 0;
while( choice != 'E') {
cls(); cout << header << menu; // Header and Menu cin.get(choice); choice = toupper(choice);
cls(); cout << header << endl; // Header switch( choice)
{ case 'B': // Booking if( !getPassword() )
{ cout << "Access denied!" << endl;
go_on();
} else { cout << "Welcome!\n\n"
<< "Do you want to change the password? (y/n)"; if( getYesOrNo() == 'Y')
{ if( changePassword() ) cout << "Password changed!" << endl;
else cout << "Password unchanged!" << endl; go_on();
} // Place statements for booking here
} break;
case 'E':
cls(); cout << "\n Bye Bye!" << endl;
break;
} } // End of while return 0;
}
Trang 3References and Pointers This chapter describes how to define references and pointers and how
to use them as parameters and/or return values of functions In this context, passing by reference and read-only access to arguments are introduced.
Trang 4222 C H A P T E R 1 2 R E F E R E N C E S A N D P O I N T E R S
// Ref1.cpp // Demonstrates the definition and use of references //
-#include <iostream>
#include <string>
using namespace std;
float x = 10.7F; // Global int main()
{
// double &ref = x; // Error: different type!
rx *= 2;
cout << " x = " << x << endl // x = 21.4
<< " rx = " << rx << endl; // rx = 21.4
const float& cref = x; // Read-only reference cout << "cref = " << cref << endl; // ok!
// ++cref; // Error: read-only!
const string str = "I am a constant string!";
// str = "That doesn't work!"; // Error: str constant! // string& text = str; // Error: str constant!
const string& text = str; // ok!
cout << text << endl; // ok! Just reading return 0;
}
Object names: The object in
memory
10.7
x, rx
■ DEFINING REFERENCES
Example
float x = 10.7, &rx = x;
Sample program
Trang 5D E F I N I N G R E F E R E N C E S 223
A reference is another name, or alias, for an object that already exists Defining a refer-ence does not occupy additional memory Any operations defined for the referrefer-ence are performed with the object to which it refers References are particularly useful as parame-ters and return values of functions
䊐 Definition
The ampersand character, &, is used to define a reference Given that Tis a type, T&
denotes a reference to T
Example: float x = 10.7;
float& rx = x; // or: float &rx = x;
rxis thus a different way of expressing the variable xand belongs to the type “reference
tofloat” Operations with rx, such as
Example: rx; // equivalent to x;
will automatically affect the variable x The &character, which indicates a reference, only occurs in declarations and is not related to the address operator &! The address operator returns the address of an object If you apply this operator to a reference, it returns the address of the referenced object
Example: &rx // Address of x, thus is equal to &x
A reference must be initialized when it is declared, and cannot be modified
subse-quently In other words, you cannot use the reference to address a different variable at a later stage
䊐 Read-Only References
A reference that addresses a constant object must be a constant itself, that is, it must be defined using the constkeyword to avoid modifying the object by reference However,
it is conversely possible to use a reference to a constant to address a non-constant object.
Example: int a; const int& cref = a; // ok!
The reference crefcan be used for read-only access to the variable a, and is said to be a
read-only identifier.
A read-only identifier can be initialized by a constant, in contrast to a normal refer-ence:
Example: const double& pi = 3.1415927;
Since the constant does not take up any memory space, the compiler creates a temporary object which is then referenced
Trang 6224 C H A P T E R 1 2 R E F E R E N C E S A N D P O I N T E R S
// Ref2.cpp // Demonstrating functions with parameters // of reference type
//
-#include <iostream>
#include <string>
using namespace std;
// Prototypes:
bool getClient( string& name, long& nr);
void putClient( const string& name, const long& nr);
int main() {
string clientName;
long clientNr;
cout << "\nTo input and output client data \n"
<< endl;
putClient( clientName, clientNr);
else cout << "Invalid input!" << endl;
return 0;
}
bool getClient( string& name, long& nr) // Definition {
cout << "\nTo input client data!\n"
<< " Name: ";
if( !getline( cin, name)) return false;
cout << " Number: ";
if( !( cin >> nr)) return false;
return true;
}
// Definition
void putClient( const string& name, const long& nr)
{ // name and nr can only be read! cout << "\n - Client Data -\n"
<< "\n Name: "; cout << name
<< "\n Number: "; cout << nr << endl;
}
■ REFERENCES AS PARAMETERS
Sample program
Trang 7R E F E R E N C E S A S P A R A M E T E R S 225
䊐 Passing by Reference
A pass by reference can be programmed using references or pointers as function
parame-ters It is syntactically simpler to use references, although not always permissible
A parameter of a reference type is an alias for an argument When a function is called,
a reference parameter is initialized with the object supplied as an argument The function can thus directly manipulate the argument passed to it
Example: void test( int& a) { ++a; }
Based on this definition, the statement
test( var); // For an int variable var
increments the variable var Within the function, any access to the reference a auto-matically accesses the supplied variable, var
If an object is passed as an argument when passing by reference, the object is not copied Instead, the address of the object is passed to the function internally, allowing the function to access the object with which it was called
䊐 Comparison to Passing by Value
In contrast to a normal pass by value an expression, such as a+b, cannot be used as an argument The argument must have an address in memory and be of the correct type
Using references as parameters offers the following benefits:
■ arguments are not copied In contrast to passing by value, the run time of a pro-gram should improve, especially if the arguments occupy large amounts of mem-ory
■ a function can use the reference parameter to return multiple values to the calling
function Passing by value allows only one result as a return value, unless you resort to using global variables
If you need to read arguments, but not copy them, you can define a read-only reference
as a parameter
Example: void display( const string& str);
The function display()contains a string as an argument However, it does not gener-ate a new string to which the argument string is copied Instead, stris simply a refer-ence to the argument The caller can rest assured that the argument is not modified within the function, as stris declared as a const
Trang 8226 C H A P T E R 1 2 R E F E R E N C E S A N D P O I N T E R S
// Ref3.cpp // Demonstrates the use of return values with // reference type
//
-#include <iostream>
#include <string>
using namespace std;
// Returns a
double& refMin( double&, double&); // reference to
// the minimum
int main() {
double x1 = 1.1, x2 = x1 + 0.5, y;
cout << "x1 = " << x1 << " "
<< "x2 = " << x2 << endl;
cout << "Minimum: " << y << endl;
cout << "x1 = " << x1 << " " // x1 = 2.1
<< "x2 = " << x2 << endl; // x2 = 1.6
// the minimum
cout << "x1 = " << x1 << " " // x1 = 2.1
<< "x2 = " << x2 << endl; // x2 = 2.6
// x1 is the minimum cout << "x1 = " << x1 << " " // x1 = 10.1
<< "x2 = " << x2 << endl; // x2 = 2.6
// x2 is the minimum cout << "x1 = " << x1 << " " // x1 = 10.1
<< "x2 = " << x2 << endl; // x2 = 7.6 return 0;
}
double& refMin( double& a, double& b) // Returns a { // reference to return a <= b ? a : b; // the minimum }
The expression refMin(x1,x2)represents either the object x1or the object x2, that is, the object containing the smaller value
✓ NOTE
■ REFERENCES AS RETURN VALUE
Sample program
Trang 9R E F E R E N C E S A S R E T U R N V A L U E 227
䊐 Returning References
The return type of a function can also be a reference type The function call then repre-sents an object, and can be used just like an object
Example: string& message() // Reference!
{
static string str = "Today only cold cuts!";
return str;
}
This function returns a reference to a static string,str Pay attention to the following point when returning references and pointers:
The object referenced by the return value must exist after leaving the function.
It would be a critical error to declare the string stras a normal autovariable in the functionmessage() This would destroy the string on leaving the function and the ref-erence would point to an object that no longer existed
䊐 Calling a Reference Type Function
The function message() (mentioned earlier in this section) is of type “reference to
string.” Thus, calling
message()
represents a stringtype object, and the following statements are valid:
message() = "Let's go to the beer garden!";
message() += " Cheers!";
cout << "Length: " << message().length();
In these examples, a new value is first assigned to the object referenced by the function call Then a new string is appended before the length of the referenced string is output in the third statement
If you want to avoid modifying the referenced object, you can define the function type
as a read-only reference
Example: const string& message(); // Read-only!
References are commonly used as return types when overloading operators The oper-ations that an operator has to perform for a user-defined type are always implemented by
an appropriate function Refer to the chapters on overloading operators later in this book for more details However, examples with operators from standard classes can be pro-vided at this point
Trang 10228 C H A P T E R 1 2 R E F E R E N C E S A N D P O I N T E R S
Reference to cout
cout << "Good morning"
<<'!';
// Ref4.cpp // Expressions with reference type exemplified by // string assignments
//
-#include <iostream>
#include <string>
#include <cctype> // For toupper() using namespace std;
int main() {
string text("Test with assignments \n");
strToUpper(text);
cout << text << endl;
strToUpper( text = "Flowers");
cout << text << endl;
strToUpper( text += " cheer you up!\n");
cout << text << endl;
return 0;
}
void strToUpper( string& str) // Converts the content { // of str to uppercase int len = str.length();
for( int i=0; i < len; ++i) str[i] = toupper( str[i]);
}
■ EXPRESSIONS WITH REFERENCE TYPE
Example: Operator << of class ostream
cout << "Good morning" << '!';
Sample assignments of class string