2

I've made a custom class which involves a ton of number and string computation. I've made my class immutable by only providing accessors and no mutators. Once the object is constructed, there is no changing a single property of it.

My question from here is, currently all of my functions are pass by value. If you have an immutable object, is pass by reference even needed anymore? Is pass by value wasteful in terms of memory since copies need to constantly be created?

For example:

class MyInteger
{
    private:
        const int val;

    public:
        MyInteger(const int a) : val(a) { };    
        int getValue() const { return val; }
        MyInteger add(const MyInteger other)
        {
            return MyInteger(val + other.getValue());   
        }
}
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
Hatefiend
  • 3,416
  • 6
  • 33
  • 74
  • 1
    Pass by reference to const. I think for built in types it does not really matter. –  Feb 04 '17 at 14:44
  • @RawN I don't understand what you mean? – Hatefiend Feb 04 '17 at 14:45
  • `getValue` must be `const`. – Christian Hackl Feb 04 '17 at 14:45
  • @ChristianHackl yes sorry I forgot to add that in this tiny demo snippet. I just added that code for visual aid, my question above doesn't really have anything to do with that implementation. – Hatefiend Feb 04 '17 at 14:46
  • @Hatefiend Passing by value makes a copy. It invokes a parameter's constructor if there is one. That's an overhead. Passing by reference to const does not invoke underlying data's constructor / does not make a copy. –  Feb 04 '17 at 14:46
  • @Hatefiend What's the problem actually?? – πάντα ῥεῖ Feb 04 '17 at 14:49
  • @RawN Right, I understand this. So when is it optimal to use pass by value instead of pass by reference? If your reply is that it depends on what I am doing then realize that I'm asking this because of the immutability of the class. If there's nothing inside the object that can be changed, doesn't that make more sense to the pointlessness of passing a reference to the object? On the other hand, copying takes time and resources so I don't know what to do. Hence, why I am here asking. – Hatefiend Feb 04 '17 at 14:53
  • @Hatefiend Scott Meyers "Effective C++" from 2005, item no. 19. Very well explained. –  Feb 04 '17 at 15:00
  • 1
    @Hatefiend: Non-const references to immutable classes do not make sense. Const references do make sense. About the performance of copying vs. const references, it normally doesn't matter because your computer is too fast and your compiler too smart. Unless profiling tells you otherwise, a good rule of thumb is to pass immutable "big" objects of class types by `const&` and primitive objects as well as iterators and functors by value. With this in mind, little can go wrong and you will only have to reconsider the rule in very specific situations. – Christian Hackl Feb 04 '17 at 15:01
  • @ChristianHackl Thanks, I understand a bit better now. Pass by reference is more annoying wouldn't you say because you have to write `&` and `*` far more often? My class has only around `8` bytes of variables so perhaps it makes more sense to use pass by value. – Hatefiend Feb 04 '17 at 15:04
  • @Hatefiend: First of all, `*` is for pointers, not for references. And no, `&` is not annoying because that's just the way C++ works. Better get used to it! :) Don't think too much about such micro optimisations. If I were you, I'd just pass by `const&`. About the byte count... what if you add a data member at a later point and have already used pass-by-value with the class at 1000 other places in your code? – Christian Hackl Feb 04 '17 at 15:12

1 Answers1

2

Pass-by-value requires copying. If your class is large and copying costs, you could make it pass-by-reference to avoid such copy.

Since it's immutable you can pass it by reference-to-const.

class MyInteger
{
    private:
        const int val;

    public:
        MyInteger(const int a) : val(a) { };    
        int getValue() const { return val; }

        MyInteger add(const MyInteger& other) const // Note this is passed by reference to const now
        //                           ~
        {
            return MyInteger(val + other.getValue());   
        }
}
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • 2
    `/ /Note that this is pass by value.` You should remove this comment. – Christian Hackl Feb 04 '17 at 14:46
  • I forgot to add that `const` when I was thinking up my question. I'm not too sure what `const` has to do with my question besides the small optimization that 'adding' shouldn't modify the `other` variable. I still however do not really grasp when to use pass by value. – Hatefiend Feb 04 '17 at 14:50
  • @Hatefiend have a look here: [link](http://stackoverflow.com/questions/270408/is-it-better-in-c-to-pass-by-value-or-pass-by-constant-reference) – peval27 Feb 04 '17 at 14:54
  • Interesting. Lots of conflicting answers in that thread. My class has three members: `unsigned char*`, `bool`, `size_t`. Doesn't seem to large, right? Pass by value might be okay? – Hatefiend Feb 04 '17 at 15:02
  • 1
    @Hatefiend As a rule of thumb you could consider to pass a `uint8_t` rather by value than using a `const` reference. That would likely occupy less stack space then. I'm not a friend of such micro optimizations though. – πάντα ῥεῖ Feb 04 '17 at 15:02
  • @Hatefiend It's subtle. It's not easy to determine that without exact performace profile. Anyway, if you're not sure, then use passing-by-reference would be fine. – songyuanyao Feb 04 '17 at 15:05
  • @Hatefiend: The only real conflict in the C++ community, even among renowned experts, is whether the pre-C++11 rules for pass-by-const-ref vs. pass-by-value still apply to the modern C++ world. – Christian Hackl Feb 04 '17 at 15:07