Reputation: 2009
I'm just beginning to learn basic C++ syntax and I'm slightly confused on a piece of code I came across.
For a class created called MyString, there was an operator overloading defined as:
ostream& operator<<(ostream& os, const MyString& s)
{
os << s.data;
return os;
}
Then in some driver function the statement:
cout << s3 << endl;
Is ran, where s3 is of object type MyString. The result prints out the value of s3.
I don't quite understand how this statement functions. After messing with it it seems like a copy constructor is called once and then 3 objects are deconstructed. How exactly does this line work? It seems like the operator accepts a reference to an ostream and MyString, but isn't endl neither? Also why would there only be 1 copy constructor called when there are two instances of the "<<" used? Maybe I'm not even asking the right questions or my questions don't even make sense because I feel really confused about what is going on in these lines. If that is the case, can someone please expound on just a general explaination of what is going on?
Upvotes: 3
Views: 1809
Reputation: 4505
Rules of the language says that if a non member function (operator<< is a non-member function of class MyString) is defined in the same namespace as MyString than this non member function can be chosen by the compiler to resolve that call (as explained by one of the respondents) I do not use here the standard terminology, if anybody has a more accurate description of this principle please let us know.
Upvotes: 0
Reputation: 60034
I guess the copy constructor could be generated by your compiler for cout. A stream is a rather complex object, but the choice of c++ is to provide such syntax sugar (like inline constructors) to abstract some detail. The other answers already pointed out the essential point that using references no copy is performed for parameter passing.
Upvotes: 0
Reputation: 16217
You can break it down a bit:
cout // this is the ostream your inserting to (stdout)
<< s3 // this calls your defined operator that writes s.data
<< endl; // this calls the operator<< for std::endl
ostream& operator<<(ostream& os, const MyString& s)
{
// here os is the ostream (stdout) you're using via cout
// s is s3 that you passed in
os << s.data; // this calls operator<< for data
return os; // this returns the reference so the subsequent call to << endl can append to the stream
}
Upvotes: 1
Reputation: 75150
This is a very general question, but I'll try to clear up your misunderstandings.
When you say ostream& operator<<(ostream& os, const MyString& s) { ... }
, you're just defining a function that takes an ostream&
as the first parameter and a const Mystring&
as the second parameter, and returning an ostream&
. The function happens to be named operator<<
and can be called by the shorthand syntax x << y
to call operator<<(x, y)
.
When you do cout << s3 << endl;
, it is the same as doing operator<<(operator<<(cout, s3), endl);
.
Neither the copy constructor nor the destructor for MyString
is being called from this code. The messages you are seeing are from somewhere else.
Upvotes: 7
Reputation: 86509
The MyString copy constructor is not needed to call this statement, because MyString is passed as a reference to the custom operator<< for MyString.
The endl is not sent to the custom operator<< for MyString.
Upvotes: 0