Swapping, and Operator= via the "Swap Trick"

Dr. Lawlor, CS 202, CS, UAF

There's a nice built-in STL function named "std::swap" that takes two variables, and swaps their values.  You call it like:
int a=7, b=13;
std::swap(a,b);
return a;

(Try this in NetRun now!)

This returns 13, the old value of b.  std::swap is implemented something like this copy-to-temp version:
template <class T>
void myswap(T &a,T &b) {
T tmp=a;
a=b;
b=tmp;
}

int foo(void) {
int x=7, y=13;
std::swap(x,y);
return x;
}

(Try this in NetRun now!)

It's surprisingly handy to have a member function named "swap", that just swaps everything inside this object, with another object:
class bar {
public:
int x,y;
void swap(bar &v) {
std::swap(x,v.x);
std::swap(y,v.y);
}
bar(int x_,int y_) :x(x_), y(y_) {}
friend std::ostream &operator<<(std::ostream &s,const bar &b) {
s<<b.x<<","<<b.y;
return s;
}
};
int foo(void) {
bar a(2,3), b(11,14);
a.swap(b);
std::cout<<"a="<<a<<" and b="<<b<<"\n";
return 0;
}

(Try this in NetRun now!)

One place where swap is useful is in "ping-pong" algorithms, where you need to iteratively compute new values.  The obvious way to do this involves creating and assigning objects to store those new values, but it's often more efficient (especially with larger objects) to just swap the old and new values:
int foo(void) {
bar a(0.4,1.0), b(0,0);
for (int i=0;i<4;i++) {
// compute new value into b
b.x=a.x*a.x-a.y*a.y;
b.y=2*a.x*a.y;
a.swap(b); // swap new value into a
}
std::cout<<"a="<<a<<" and b="<<b<<"\n";
return 0;
}

(Try this in NetRun now!)

For big classes, that store a lot of data, swap can just move the pointers around, rather than deallocating and reallocating data.  Thus you can swap two gigabyte-long arrays in just nanoseconds!

// A nice wrapper around a dynamically allocated array of integers.
class SmartArray {
private:
int *data;
int length;
public:
SmartArray(int len) {
data=new int[len]; // allocate space
length=len;
}
int &operator[](int index) {
if (index<0 || index>=length) { // bounds-check the array index
cout<<"Index "<<index<<" out of bounds!\n";
exit(1);
}
return data[index];
}
void swap(SmartArray &a) {
std::swap(data,a.data);
std::swap(length,a.length);
}
~SmartArray() {
delete[] data; // free space
data=0; /* zero out our pointer, to indicate we're gone */
length=-1;
}
private: // law of big three
SmartArray(const SmartArray &a); // don't call this
SmartArray &operator=(const SmartArray &a); // don't call this
};

int foo(void) {
int n=5; cin>>n;
SmartArray arr(n); // array has n integers
for (int i=0;i<n;i++) arr[i]=10*i;
SmartArray demo(0); demo.swap(arr);
for (int i=0;i<n;i++) cout<<"demo["<<i<<"] = "<<demo[i]<<"\n";
return 0; // destructor automatically deallocates array!

}

(Try this in NetRun now!)

Another place swap comes in handy is in writing your class's assignment operator.  Normally, the assignment operator requires you to deallocate your class's old memory, allocate space for the new data, and copy the new data in.  But with swap, all you need to do is make a new temporary object, and swap yourself into him:
	SmartArray &operator=(const SmartArray &a) 
{ // assignment operator (via the swap trick)
SmartArray temp(a); // copy a's data
swap(temp); // take copied data, moves our data to temp
return *this;
}
(Try this in NetRun now!)