Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I return an immutable parameter from a method, unchanged, and without a copy in c++?

How do I return a parameter from a method, unchanged, and without a copy in c++?

// This is more or less the desired signature from the caller's point of view
SomeImmutableObject ManipulateIfNecessary(SomeImmutableObject const& existingObject)
{
    // Do some work…
    // ...

    if (manipulationIsNeccessary)
    {
        // Return a new object with new data etc (preferably without another copy)...
        return SomeImmutableObject(...);
    }
    else
    {
        // Return the original object intact (but with no further copies!)...
        return existingObject;
    }
}

An example is C#'s String.Trim method. C# strings are immutable and if Trim doesn't have to do any work, a reference to the existing string is returned, otherwise a new string object with the trimmed content is returned.

How would I mimic this semantic in C++ given something close to the above method signature?

like image 534
Roger B Avatar asked Mar 13 '15 06:03

Roger B


People also ask

How do you break immutability?

So, even though, the field which is pointing to Date or Collection or array object is final, you can still break the immutability of the class by breaking Encapsulation by returning a reference to the original mutable object.

Can you change values of an immutable object?

The immutable objects are objects whose value can not be changed after initialization. We can not change anything once the object is created. For example, primitive objects such as int, long, float, double, all legacy classes, Wrapper class, String class, etc. In a nutshell, immutable means unmodified or unchangeable.

What does immutable mean and how are values held in string objects changed?

An Immutable Object means that the state of the Object cannot change after its creation. Here the String is immutable means that you cannot change the object itself, but you can change the reference to the object.


1 Answers

Your object must be a reference type for this to work. Let's give a toy example for strings:

class RefString {
public:
    RefString() : ref(new std::string()) { }
    RefString(const std::string& str) : ref(new std::string(str)) { }

    RefString trim_trailing_newline() {
        if (ref->back() == '\n') {
            return RefString(ref->substr(0, ref->size()-1));
        }

        return *this;
    }

    size_t size() { return ref->size(); }

private:
    std::shared_ptr<std::string> ref;
};

int main(int argc, char** argv) {
    RefString s("test\n");
    std::cout << s.size() << "\n";
    std::cout << s.trim_trailing_newline().size() << "\n";
    return 0;
}
like image 67
orlp Avatar answered Sep 27 '22 22:09

orlp