1

I have looked at the disassembly for the following code and found that the result is often the same (or very similar) for both test functions. I am wondering what the difference is between the two functions and if not, is there any history or reason for this existing?

struct test
{
    int x;

    test&      testfunction1()  { x++; return *this; }
    void       testfunction2()  { x++; }
};

edit: with my question being answered so quickly I am now wondering what reasons you would choose to use one over the other? it seems for the sake of 'freedom' one should always use a reference over the directly modifying the data.

Ken White
  • 123,280
  • 14
  • 225
  • 444
james ray
  • 97
  • 7
  • With `testfunction1` you can do cool stuff like `std::cout << test1.testfunction1().x;` – user4581301 Oct 28 '21 at 03:15
  • C++ derives from C, and C didn't have references; `testfunction2` was the only way to do it. – Mark Ransom Oct 28 '21 at 03:25
  • 2
    Returning reference is convenient for chain operation. Like `test.funA().funB().funC()...` – Louis Go Oct 28 '21 at 03:35
  • @LouisGo that's true, but how often have you done something like that? It will leave people scratching their heads. – Mark Ransom Oct 28 '21 at 04:01
  • 1
    @MarkRansom: It’s not exactly [unheard of](https://en.m.wikipedia.org/wiki/Fluent_interface). – Davis Herring Oct 28 '21 at 04:31
  • @DavisHerring true again. But it's mostly talked about in a theoretical context; like [Duff's device](https://stackoverflow.com/q/514118/5987) it's too esoteric to find it in real code. I have yet to find a place where I'd find it useful. – Mark Ransom Oct 28 '21 at 04:41
  • @MarkRansom Yes it depends on the context. I found this kind of style in C#, java, javascript more frequently. – Louis Go Oct 28 '21 at 05:32
  • The only difference between the two functions (apart from their name) is in what they return to the immediate caller. `testfunction1()` returns a reference, so can be used in `some_test.testfunction1().testfunction1()` (to call `testfunction1()` twice on the same object). Such chaining is not possible after a call of `testfunction2()`. In practice, such chaining is often used for input from or output to streams (e.g. `cout << 1 << 2` actually does `cout.operator<<(1).operator<<(2)`) which would be impossible if `operator<<()` for output streams did not return a reference to stream it acts on. – Peter Oct 28 '21 at 07:05

1 Answers1

2

The functionality is almost the same, difference is the first enables the ability to chain methods. This design pattern is called fluent interface. It is supposed to provide an easy-readable, flowing interface, that often mimics a domain specific language. Using this pattern results in code that can be read nearly as human language.

Widget w = new Widget();
w.setHeight(1024).setWidth(768).setColor(255,0,0); // easy to follow

Why people don't do it everywhere? It is matter of preference, readability, coding convention of the group, it takes more effort to design you API in such way. Also if you don't use the returned value, it can produce warning or error expression result is unused when compiling C++ with some flags.

The common usage of testfunction1() example is using of overloaded operators of output for something, often you can see in code

std::cout << "The results are: " << SomeUserDefinedStruct << " and "<< SomeUserDefinedStruct2 << std::endl;

The overloaded version of operator<< is returning reference to std::ostream, which is chained to others.

ygroeg
  • 143
  • 9