To avoid creating unnecessary objects, theoretically increasing the speed of the program (if the objects are large), I always try to use references when passing parameters to a function and returning them from a function. For example:

friend ostream &operator<<(ostream &stream, three_cl &obj); 

Is the thought path correct?

Those. This version of the previous function is worse:

 friend ostream &operator<<(ostream stream, three_cl obj); 

A copy constructor creates two objects here: stream and obj , which are destroyed when the operator is overloaded from the function.

If the result is the same, better to use links?

  • one
    Premature optimization is the source of all evil. At the moment, the compiler takes care of most of the optimization of your code. Therefore, to start, make an alpha / beta / release release version of your program, and after that, check if its speed is sufficient. And then take up the optimization. - Makarenko_I_V

2 answers 2

First, this operator

 friend ostream &operator<<(ostream stream, three_cl obj); 

incorrect. The std::ostream has a remote copy constructor. Therefore, you cannot pass an object of class std::ostream by value. And besides, from the function declaration, it turns out that the function returns a reference to the local object std::ostream , which leads to undefined program behavior.

Of course, for user-defined types, it is better to pass objects by reference. And functions can be separately overloaded for lvalue links and rvalue links.

Here's how, for example, the push_back function for the std::vector class is overloaded

 void push_back(const T& x); void push_back(T&& x); 

That is, one function is defined for a constant lvalue reference; the second is for an rvalue reference.

In your example operator operator << also better to declare the second parameter as a constant link. In this case, you can call the operator for temporary objects, since the constant reference can be "attached" to the temporary objects: Yes, and the objects themselves, for which the operator is called, can also be constant.

 friend std::ostream & operator <<( std::ostream &stream, const three_cl &obj ); 

For fundamental types, there is no need to pass objects by constant reference instead of objects by value, if you are not going to write a generic template function. For example, in the C ++ standard, the following operator << for fundamental types are defined as

 basic_ostream<charT,traits>& operator<<(bool n); basic_ostream<charT,traits>& operator<<(short n); basic_ostream<charT,traits>& operator<<(unsigned short n); basic_ostream<charT,traits>& operator<<(int n); basic_ostream<charT,traits>& operator<<(unsigned int n); // и другие операторы для фундаментальных типов 

As you can see, the arguments are passed by value.

As for the return value, you must take into account that you cannot return a reference from a function to a local object (unless it has a static memory class).

Returning a link allows you to combine calls of several functions in a chain. For example, in the class std::basic_string operator operator += declared as returning a link. Thanks to this you can write, for example,

 std::string s( "Hello " ); std::cout << ( ( s += "World" ) += '!' ) << std::endl; 

And this is rather a question not in style, but in program efficiency and flexibility. :)

  • Thank you for the comprehensive answer. This is really more a question of efficiency, but I didn’t know what to write in the title :) I would like to clarify: const T &var - can such a parameter of the function accept both lvalue and rvalue arguments? And, is it possible to consider such a parameter universal (everywhere applicable): T &&var - after all, rvalue references also accept lvalue arguments? - Lurking Elk
  • one
    @Dim Team When the parameter is declared as cons T & var, then you can set the argument to both lvalue and rvale. For an i-template parameter declared as T && var, you can pass lvalue. For a non-template parameter, you cannot do this. - Vlad from Moscow
  • And in this declaration, basic_ostream<charT,traits>& operator<<(bool n); is the required stream not passed as an argument, because all possible streams are defined in basic_ostream ? - Lurking Elk
  • @Dim Team For these types, the operator << is a member of the basic_ostream class itself, and not a "free" function. - Vlad from Moscow
  • one
    @Dim Team Yes, if the template parameter is declared as const T & var, then it can accept both lvalue and rvalue. The problem is which type is actually displayed for the parameter based on the argument. You can read about these rules in the book Effective Modern C ++: 42 Specific Ways to C ++ 11 and C ++ 14 (Scott Meyers, 2015) - Vlad from Moscow

For example, I use references in two cases:

  1. To return a value to the parameter
  2. To speed up the work (but only in extreme cases)
  • Для ускорения работы (но только в крайних случаях) why only in the extreme, what's wrong with the links? - Lurking Elk
  • An incorrectly written function can change a variable ... But this is what I write, if speeds are not important ... - sitev_ru
  • @sitev_ru, pass a link to a constant object. - awesoon