3

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?

nitin_cherian
  • 6,405
  • 21
  • 76
  • 127
KWJ2104
  • 1,959
  • 6
  • 38
  • 53
  • Which C++ book are you learning from? – Greg Hewgill Dec 05 '11 at 21:02
  • 3
    this is too broad to answer here, you need to refer to a good book tbh. – Nim Dec 05 '11 at 21:02
  • C++ Primer 4th Ed., by Lippman – KWJ2104 Dec 05 '11 at 21:02
  • 1
    You call that basic c++ syntax ? Also, overloading operators when you have just started learning c++ :) ? – ScarletAmaranth Dec 05 '11 at 21:05
  • If you want us to explain how many copies of `MyString` instances there are, you will need to provide a more complete code sample. There is no way we can diagnose this issue without a complete example. – André Caron Dec 05 '11 at 21:10
  • I think, this is actually three questions: a) [what is call by reference?](http://stackoverflow.com/q/57483/1025391) b) [what is operator overloading?](http://stackoverflow.com/q/4421706/1025391) c) [what is operator precedence?](http://stackoverflow.com/questions/5473107/operator-precedence-vs-order-of-evaluation) - a lot of information though – moooeeeep Dec 05 '11 at 21:20

5 Answers5

7

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.

Seth Carnegie
  • 73,875
  • 22
  • 181
  • 249
1

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
}
AJG85
  • 15,849
  • 13
  • 42
  • 50
0

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.

Andy Thomas
  • 84,978
  • 11
  • 107
  • 151
0

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.

CapelliC
  • 59,646
  • 5
  • 47
  • 90
0

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.

Ghita
  • 4,465
  • 4
  • 42
  • 69
  • I had a direct experience of this behaviour when I switched from MSVC2003 where MSVC2005: I had code like ofstream("log") << "here..\n". After the switch instead of the message I had garbage (the pointer value) in the file. – CapelliC Dec 06 '11 at 08:03