swapping.cppΒΆ
This code demonstrates:
- How to overload
operator<<
for convenient printing of vectors of strings. - How (and how not) to write a function that swaps the value of two variables.
- That C++ functions can have the same name as long as their parameters are different.
// swapping.cpp
#include "cmpt_error.h"
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// print a vector<string> in a nice format
ostream& operator<<(ostream& os, const vector<string>& v) {
int n = v.size();
if (n == 0) { // empty vector
os << "{}";
} else if (n == 1) { // vector with 1 element
os << "{" << v[0] << "}";
} else { // vector with 2 or more elements
os << "{" << v[0];
for(int i = 1; i < v.size(); ++i) {
os << ", " << v[i];
}
os << "}";
}
return os;
}
// By default, C++ passes parameters by value, i.e. it makes a copy of the
// value passed to the function. One consequence of that is that a function
// cannot modify the value of a passed-in variable, and so swap cannot be
// written using pass-by-value parameters.
void swap_wrong(int a, int b) {
int temp = a;
a = b;
b = temp;
}
// If you pass a function a *pointer* to a variable, then the function *can*
// modify the value of the variable being pointed to.
//
// For example:
//
// int x = 2;
// int y = 3;
// swap_pointer(&x, &y); // must pass address of x and y
// cout << x << " " << y; // prints 3 2
//
// The pointers themselves are passed by value, and so the function can't
// change the original pointers. It can only change the value the pointers
// point to.
//
// It helps to draw a diagram showing how the function call works.
void swap_pointer(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
// Using the & operator as shown, C++ lets you pass variables by reference.
// This means no copy of the variable's value is made, and the function can
// modify the value of the variable if it needs to.
//
// For example:
//
// int x = 2;
// int y = 3;
// swap_reference(x, y);
// cout << x << " " << y; // prints 3 2
//
// The advantage of this approach is that you don't need to write &x and &y
// when calling swap_reference.
void swap_reference(int& a, int& b) {
int temp = a;
a = b;
b = temp;
}
// Pass by reference works with any C++ data type. The "="" operator in the
// statement "a = b;" makes a copy of the entire vector<string>, which could
// be time-consuming if it's big!
//
// Also notice that the name of this function is swap_reference, which is the
// same as the name of the previous function. C++ can always tell which one
// you mean to call by checking the type of the parameters that are passed.
void swap_reference(vector<string>& a, vector<string>& b) {
vector<string> temp = a;
a = b;
b = temp;
}
// C++ generics (i.e. templates), are a way to pass a *type* as a parameter
// to function. Here, T is any type that can be constructed and works with
// "=". This includes all basic C++ types, and most standard library types.
// Thus, swap_generic will swap any two objects of the same type.
//
// Modern C++ has embraced generics, and they are used throughout the standard
// library. Many of the newer features of C++ were added to facilitate the use
// of generic programming.
template<class T>
void swap_generic(T& a, T& b) {
T temp = a;
a = b;
b = temp;
}
int main() {
int x = 3;
int y = 5;
cout << "x = " << x << ", y = " << y << "\nswap_wrong(x, y)\n";
swap_wrong(x, y);
cout << "x = " << x << ", y = " << y << "\n\n";
x = 3;
y = 5;
cout << "x = " << x << ", y = " << y << "\nswap_pointer(x, y)\n";
swap_pointer(&x, &y);
cout << "x = " << x << ", y = " << y << "\n\n";
x = 3;
y = 5;
cout << "x = " << x << ", y = " << y << "\nswap_reference(x, y)\n";
swap_reference(x, y);
cout << "x = " << x << ", y = " << y << "\n\n";
vector<string> v = {"cat", "dog", "sun"};
vector<string> w = {"on", "off", "yes", "no", "up", "down"};
cout << "v = " << v << ", w = " << w << "\nswap_reference(v, w)\n";
swap_reference(v, w);
cout << "v = " << v << ", w = " << w << "\n\n";
string s = "butterfly";
string t = "frog";
cout << "s = " << s << ", t = " << t << "\nswap_generic(s, t)\n";
swap_generic(s, t);
cout << "s = " << s << ", t = " << t << "\n\n";
x = 3;
y = 5;
cout << "x = " << x << ", y = " << y << "\nswap_generic(x, y)\n";
swap_generic(x, y);
cout << "x = " << x << ", y = " << y << "\n\n";
}