Basic Explanation of little bit of C++ - c++

Can some lovely soul help me out with this one :)
Could you please explain each piece of this line of code
and what each Individual piece does? Thank you in advance.
istream & operator >>( istream & input, Registration & R )
ostream & operator <<( ostream & os, const Registration & R )

istream & operator >>( istream & input, Registration & R )
istream& means that object of type istream will be returned by reference.
operator>> is the identifier of the function, it is specifically named so that it overrides the default functionality of the >> operator (similar to how you can override the default functionality the + operator, or operator+() as a "binary" (meaning two) operator (meaning it involves two arguments).
(...) everything within the parentheses are the parameters of the function, they are the data that will be given to the function when it is called to be run.
istream& input indicates that a variable called "input" of type istream will be passed in by reference, meaning that usage of the input variable will refer to the original variable passed in from the location in which it was called and NOT a copy (see: passing by reference and passing by value).
Registration& R indicates that a variable called "R" of type Registration will be passed in by reference (see the definition above). The type Registration seems to be derived from some method for defining a type, such as from a class or a struct.
If you're looking for more information on what an object of type istream is, how it's defined, or what "it does," (along with anything else I mentioned here) I recommend running a search and looking through the wealth of free, available information online.

Related

Can we overload operator<< with the first parameter being of the type std::ostream&& instead of std::ostream&

I have learnt that we can overload operator<< as shown below :
class Person
{
public:
friend std::ostream& operator<<(std::ostream& os, const Person& obj);
};
I absolutely understand the reason for the type of the parameters being reference. For example, the first parameter is a reference because streams can't be copied and the second parameter is a reference because we want to reflect the changes(if any as in case of operator>>) made to the original object. I know that since we have a low-level const in the second parameter its state can't be changed and by using reference we avoid copying.
My question is that can we( and should we) use rvalue reference instead of lvalue reference for the first parameter as shown below:
friend std::ostream& operator<<(std::ostream&& os, const Person& obj); //note the first parameter is rvalue-reference
Is there any reason why we should/shouldn't do what is shown above? More importantly, what will happen if we do so.
Similarly, my second question is that can we make the return type to be std::ostream&& instead of std::ostream&. In this case what will happen/change.
PS: I am learning C++ and have asked this question out of curiosity. That is, to deepen my knowledge of references and overloading.
If you tried writing something like the following, the program would not compile (this was already mentioned in the comments by #PaulMcKenzie):
#include <iostream>
#include <ostream>
struct Person {
int x = 0;
};
std::ostream& operator<<(std::ostream&& os, const Person& obj)
{
return os << obj.x;
}
int main()
{
Person p;
std::cout << p;
}
You could however make the program compile by changing the last line in main into
std::move(std::cout) << p; // don't do this in real code
Then, the program would compile and output 0. However the std::cout stream will be in a moved-from state after that and should not be used anymore.
Regarding some of the comments, there seems to be a misunderstanding about what a r-value reference is. Some seem to think it is just a better l-value reference, that we had no access to before C++11.
L-value references refer to something, that can be used on the left hand side of an expression. You can think of it as an reference to an actual object, that can be changed and assigned to and so forth. An r-value reference on the other hand refers to a temporary object, something, that can be used on the right hand side of an assignment.
Suppose you had two overloads of the operator<< with the following signature.
std::ostream& operator<<(std::ostream& os, const Person& obj);
std::ostream& operator<<(std::ostream&& os, const Person& obj);
The rules are, that the first accepts either a l-value or a r-value reference. The latter accepts only r-value references. If we call the operator with a l-value (std::cout is an example to this), the first overload will be used. If we call the operator with an r-value (like with std::move(std::cout)) the second will be used. You can omit the r-value reference overload, in wich case the first one is selected all the time, but you cannot omit the first one if you want to call the operator with a l-value. However calling the operator with an l-value is the thing you almost always want:
std::cout << p; // will not compile if there is only an r-value reference overload
Now what are the use cases of r-value references? They are used to implement move semantics on objects. R-value references are used to refer to objects, that need no longer be valid after the current statement (they have no durability). While you can theoretically move the std::cout stream, just like shown above, this is not useful at all. Streams are meant to be used as objects with long livetime and not as temporaries.
So to finally answer your question: You should not do it, because streams are usually not used as temporary objects. If you really want to provide a r-value reference overload to the << operator, go ahead, but also provide a l-value overload for the normal use case of std::cout << p;.
My question is that can we( and should we) use rvalue reference instead of lvalue reference for the first parameter as shown below:
friend std::ostream& operator<<(std::ostream&& os, const Person& obj); //note the first parameter is rvalue-reference
This is technically possible (with some limitations) but is definitely very strange thing to do. Using rvalue reference usually implies the object will be “consumed” (e.g. moved-from) and shouldn’t be used in subsequent operations. But writing to a stream doesn’t consume it, generally; the stream is still available for subsequent writes.
There are no technical reasons why you can't do either of those. However, if you do, you aren't interoperating with all the other things that define ostream operators.
If the input is ostream && then you can't have an lvalue stream to the left
Person p;
std::cout << p // can't bind std::cout to ostream&&
It's bad manners to return an rvalue reference to something that you received by lvalue reference.
std::ostream&& operator<<(std::ostream& os, const Person& obj) {
// something involving obj
return std::move(os); // stealing something that shouldn't be stolen!
}
If you want to have an expression with a temporary ostream, you can. The standard library defines a template that takes an rvalue stream, applies the equivalent lvalue stream operation, and move-returns that stream.

What is the purpose of using references to function and to IO objects (as arguments)?

Why are references to IO streams used instead of streams itself?And the same question about reference to the function.Trying to study this topic I still can't understand it.
In the code below function only prints result from the given QueryResult object on its given stream.
//declaration
ostream & print(ostream & os, const QueryResult &qr);
There is no "reference to function" here. The first & is part of the return type.
ostream& print(ostream& os, const QueryResult& qr);
The function returns a ostream& and takes a ostream& as parameter, because streams cannot be copied. The QueryResult is passed as constant reference to avoid a possibly expensive copy.
As you must know already that during function call arguments are copied to the function's parameters. But IO classes don't allow to copy their objects. Hence we cannot pass object(istream or ostream ) directly. or in simpler words
Because we can’t copy the IO types, we cannot have a parameter or return type that
is one of the stream types. Functions that do IO typically pass and
return the stream through references.
one more thing.
Reading or writing an IO object changes its state, so the reference must not be const
It is useful in method chaining. The aim is to return a fresh reference to a stream that can be passed along to the next call of operator<<() in the chain.
IO object can't be copied so we can't have return or parameter of IO type. So to do IO operation we must pass reference to the IO object to do cascading.

why "istream& object" requires reference & and ifstream doesn't?

I understand no copy or assign for IO objects, so that we have to have reference sign & for istream/ostream objects. But why ifstream/ofstream or istringstream/ostringstream doesn't require a & to initialize an object? .
istream& input=cin;
ifstream infile;
infile("in");
istream needs a & and ifstream doesn't need a & to declare the variable.
Those two aren't really comparable; one has an initializer and the other doesn't.
But std::istream input = cin doesn't work because streams are not copyable. If you tried to initialize infile with an existing ifstream, you'd get the same error. Obviously, a reference entails no copying and so it works, aliasing the existing value.
Going the opposite way, if you leave out the initializer, then you can't have a reference because a reference requires an initializer. Instead, your stream will just default construct.

Confusing C++ code involving *this?

Could someone explain this code? I don't understand line 3:
MyString MyString::operator+(const MyString &str)
{
MyString ss(*this); //----> explain this part
ss += str;
return ss;
}
Thanks!
This code:
MyString ss(*this);
Says "declare a new variable of type MyString that's named ss, and initialize it as a copy of *this." Inside of a member function, this is a pointer to the receiver object (the object that the member function is acting on), so *this is a reference to the receiver object. Consequently, you can read this as "make a new MyString that's called ss and is a copy of the receiver object."
The idiom being used here is implementing operator + in terms of operator +=. The idea is to make a copy of the receiver object, use operator += to add the parameter to the copy, and then to return the copy. It's a widely-used trick that simplifies the implementation of freestanding operators given implementation of the corresponding compound assignment operator.
Hope this helps!
This is an instance of the common code reuse technique to implement one operator in terms of another.
Suppose we have already defined a compound-plus operator:
class X
{
X & operator+=(const X&);
};
This unary operator allows us to write a += b, it modifies a and returns a reference to itself. This is all fine and good. Now if we also want to provide a copying, binary plus opearator a + b, which returns a the new value by value and leaves both a and b unchanged, then we want to take advantage of the code we've already written for the compound operator. We do so by calling the unary operator on a temporary copy of a:
X X::operator+(const X & b) const { return X(*this) += b; }
^^^^^^^^
temporary copy
This is exactly what your code does, only a bit more verbosely. You could as well have written return MyString(*this) += str;
There are other idioms with follow a similar spirit, such as implementing non-const access in terms of const access, copy-assign in terms of copy-construct and swap, and move-assign in terms of move-construct and swap. It always boils down to avoiding code duplication.
It's a constructor for MyString that takes the value of the current object (of type MyString) as its argument.
From what I can tell that is a copy constructor which creates a new MyString with the contents of the current MyString object.
ss is a new string which gets constructed with a copy constructor from the original string.

Must parameter of assignment operator be reference?

When overloading assignment operator of a class in C++, must its parameter be reference?
For example,
class MyClass {
public:
...
MyClass & operator=(const MyClass &rhs);
...
}
Can it be
class MyClass {
public:
...
MyClass & operator=(const MyClass rhs);
...
}
?
Thanks!
The parameter of an overloaded assignment operator can be any type and it can be passed by reference or by value (well, if the type is not copy constructible, then it can't be passed by value, obviously).
So, for example, you could have an assignment operator that takes an int as a parameter:
MyClass& operator=(int);
The copy assignment operator is a special case of an assignment operator. It is any assignment operator that takes the same type as the class, either by value or by reference (the reference may be const- or volatile-qualified).
If you do not explicitly implement some form of the copy assignment operator, then one is implicitly declared and implemented by the compiler.
Generally, it's up to you to decide, there is no must. The first variant is common and "canonic" and is ok for any assignment operator implementation.
When the question is speed, I think you should read this article about passing-by-value technique. This means that in some cases passing by value would be more effective than passing by const reference.
Also to mention, your second variant doesn't need const keyword, because passing by value acts as if a copy was created, so the original object definitely won't be changed.
C++ Operator Overloading Guidelines suggest, that the assignment operator gets a const reference. According to the site, the reason is that we do not want to change the argument (since const), but just the left hand side of the operator. Thus it saves time to pass it by reference.
It also points to the reason, why also a reference is returned by the assignment operator - operator chaining. In order to get a = (b = 1) working, it's necessary that (b = 1) returns a reference that can be assigned (=) to a.
Do you know the copy and swap idiom for exception safe assignment?
MyClass& operator=(const MyClass& rhs)
{
MyClass copy(rhs);
swap(copy);
return *this;
}
The implementation can be simplified (and in some cases sped up) via call by value:
MyClass& operator=(MyClass copy)
{
swap(copy);
return *this;
}
Ok I had this problem and I couldn't find a good answer so I'm going to share what I learned.
You could pass by value there is nothing wrong with that. (as you showed in your question.)
But the reason we pass the parameter by const reference is so the function doesn't make an actual copy of the value being called in. Its referenced, so its just pointing at that value wherever it is in the memory.
This saves processing time especially if its something big that has thousands of names...
In this case the time saved would be almost nothing.
And for the const, that ensures the user of the function that the referenced value is not going to be changed because it could be changed since you have access to the original location in the memory because its passed by reference..
If your function definition actually changes the value of the parameter being called in by const reference , it will be a compiler error, it wont let you do that. because when you put const, you are telling the compiler this value cannot be changed.