Note: I'm tagging this Python and C++ because I've seen examples in both, but the question is language-agnostic.
A function or class method that modifies an object has two choices: modify the data directly in the object in question, or create a new copy and return it while leaving the original untouched. Generally you can tell which is which by looking at what's returned from the function.
Occasionally you will find a function that tries to do both, modify the original object and then return a copy or reference to that object. Is there ever a case where this provides any advantage over doing only one or the other?
I've seen the example of the Fluent Interface or Method Chaining that relies on returning a reference to the object, but that seems like a special case that should be obvious in context.
My first bad example comes straight from the Python documentation and illustrates the problem of mutable default parameters. To me this example is unrealistic: if the function modifies its parameter then it doesn't make sense to have a default, and if it returns a copy then the copy should be made before any modifications take place. The problem only exists because it tries to do both.
def f(a, L=[]):
L.append(a)
return L
The second example comes from Microsoft C++ in the CStringT::MakeUpper
function. The documentation says this about the return value:
Returns a copy of the string but in all uppercase characters.
This leads one to expect that the original remains unchanged. Part of the problem is that the documentation is misleading, if you look at the prototype you find that it's returning a reference to the string. You don't notice this unless you look closely, and assigning the result to a new string compiles with no error. The surprise comes later.
in-place modification means change the value in a memory region, while not-in-place assignment creates a new memory region.
If you pass the object as an argument to a function, then its attributes can be modified in place.
Definition - In-place operation is an operation that changes directly the content of a given linear algebra, vector, matrices(Tensor) without making a copy. The operators which helps to do the operation is called in-place operator.
C++ Example Inc/Dec operator
// Pre-Increment: Create a new object for return and modify self.
myiterator operator++(int) {myiterator tmp(*this); operator++(); return tmp;}
// Post-Increment: modify self and return a reference
myiterator& operator++() {/* Do Stuff*/ return *this;}
There are some obvious examples in C++ where you want to modify the object and return a reference:
Assignment:
T & T::operator=(T && rhs)
{
ptr = rhs.ptr;
rhs.ptr = nullptr;
return *this;
}
This one modifies both the object itself and the argument, and it returns a reference to itself. This way you can write a = b = c;
.
IOStreams:
std::ostream & operator<<(std::ostream & os, T const & t)
{
os << t->ptr;
return os;
}
Again, this allows chaining of operations, std::cout << t1 << t2 << t3;
, or the typical "extract and check" if (std::cin >> n) { /* ... */ }
.
Basically, returning a reference to one of the input objects always serves to either chain calls or to evaluate the resulting state in some form or another, and there are several useful scenarios for this.
On the other hand, modifying an argument and then returning a copy of the object appears to be less useful.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With