L13 - String Streams and Operator Overloading

#ece244

string streams

syntax

notes

example: reading

#include <sstream> // short for string stream
#include <string>
using namespace std;

int main(void) {
	int ID;
	string name;
	string line = "1001 Joe";
	stringstream myStringStream(line);
	// after each read, check for .fail() and .eof() flags
	myStringStream >> ID; // reads 1001 into ID	
	myStringStream >> name; // reads "Joe" into name
	cout << myStringStream.str() << endl;
}
As good practice, use one stringstream object for reading, and a separate one for writing

Otherwise, you will have multiple cursors.

example: reading entire lines from standard input

getline(cin, <string>);
string command
stringstream myStringStream(command);
string arg1;
myStringStream >> arg1;
// i have no idea what's going on here i'm gonna be honest

operator overloading

where operator+ is being invoked on x, and parameter y is passed into the function.


example: fully implementing the operator+ function

When we want to implement the operator+ function on a Complex number (as an example), we have to:

  1. Pass in a parameter of type Complex (or whatever object/data type is on the RHS of the equation x + y)
  2. Compute the sum and set a new object of type Complex equal to that sum
  3. Return a newly created object of type Complex

Below is the code after it has been implemented

#include <iostream>
using namespace std;

class Complex { // complex number class
	private:
		double real, img;
	public:
		Complex() { // first constructor
			real = 0;
			img = 0;
		}
		Complex (double r, double i) { // second constructor
			real = r;
			img = i;
		}
		operator+(Complex rhs);
}

Complex::operator+(const Complex &rhs) const {
	// as good practice, we should use a reference
	// instead of a pass by value to save on memory
	Complex temp;
	temp.real = real + rhs.real;
	temp.img = img + rhs.img;
	return temp; // returning a COPY of temp (by value)
	// we can't return a reference here because the object will no longer exist
	// in the memory once this function goes out of scope
}

int main(void) {
	Complex x(3,4); // calls second constructor
	Complex y(5,6); // calls second constructor
	Complex z; // calls first constructor
	
	z = x + y;	
}

Notes:

file-20251031210049045.png

To be memory efficient, we can pass an object into the operator function in the class as a reference instead of a pass by value to save on memory

This is assuming we are not making any changes to the passed-in object.


some good terminology to know: pass-by-value and return-by-value

Value Reference
Pass by: Creating a copy of a value when we pass it in as a parameter into a function; memory inefficient. Passing in a reference to a value when we call a function; more memory efficient, but has all the caveats of references.
Return by: Returning a copy of a value in a function. For operator overloading, we always use this because returning by reference is invalid, IF the object that is referenced is created on the stack. Returning a reference to the value or object in a function. With operator overloading, we do NOT use this because the object we create is created on the stack, and is destroyed once the function goes out of scope.