2

This is working perfectly fine with g++ compiler:

class AliasTest {

private:
    int value;

public:
    const int &Value = value;
    AliasTest(int Value) {
        value = Value;
    }
};

I have read-only-access on the outside (attempted write access fails at compilation) and full access on the inside and I don't need a function. Could that become a problem for other compilers?

tadman
  • 208,517
  • 23
  • 234
  • 262
  • 9
    It can be useful. But you will find that the compiler deletes the assignment operator for classes with references as references can't be reassigned - live - https://godbolt.org/z/cWhcaoPvh . Probably better to just write a "getter" which will most likely get optimised away. – Richard Critten May 01 '23 at 23:15
  • 2
    Note that fixing the above is one of the rare cases where the [Rule of Three](https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three) doesn't necessarily apply. – user4581301 May 01 '23 at 23:18
  • 4
    [Be careful about copy-constructing an AliasTest](https://godbolt.org/z/5zq16szMv). When you create a copy of an `AliasTest` object, its `Value` will be a reference to the _original_'s `value`, not the copy's. – Nathan Pierson May 02 '23 at 01:10
  • I understand. Thank you very much for the code examples. Out of curiosity: wouldn't adding assignment- and copy-constructor solve most of the problems? Here https://godbolt.org/z/8zdx39vEn I tried fixing it without rule of three as user4581301 already suggested. – bugblatterbeast May 02 '23 at 08:47

1 Answers1

2

Objects with references in them are not copy assignable and are not move assignable. And there is no way around that.

Even if you don't care about assigning, the const reference provides minimum future flexibility, which is the whole point of getters. For example, if you decide that int is not good enough, and you need atomic<int>, there is no way to preserve this interface. But if you had a proper getter, you could simply fetch the atomic value and return it from the getter as a regular int and preserve the interface.

Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
  • That is of course a very reasonable concern. However I think that (in a few special situations) it can also be reasonable, to sacrifice future flexibility for performance. In the use case I have in mind, I'm expecting easily up to 10M accesses per second and I'm not absolutely sure, if I can rely on the compiler to optimize away a getter function. – bugblatterbeast May 02 '23 at 08:56
  • 2
    @bugblatterbeast Assuming the getter is trivial and defined inside the class, you can 100% rely on the compiler to inline it all the time. If this is a performance concern, you're wasting your time even thinking about it. Compilers are very good at optimizing stuff like this. Just look at all the standard containers, all of them have getters instead of providing direct access. https://godbolt.org/z/9e158feP9 – Aykhan Hagverdili May 02 '23 at 11:33
  • 2
    @bugblatterbeast in fact, the reference method is very likely less performant. It makes your objects larger. Without the reference, your objects take up 4 bytes and are trivially initializable. With the reference, your objects are very likely 16 bytes (4x the size!) and more crucially are no longer trivially i initializable. The increase in size will lead to cache misses and slower access. Furthermore, the compiler might sometimes not be able to detect that you're accessing `value` through `Value` and might have to dereference the pointer and get it indirectly, making the access slower. – Aykhan Hagverdili May 02 '23 at 11:40
  • 1
    @bugblatterbeast This is to say, when you make a change like this with the intention of optimization, you should always profile it to see if it's actually optimized or if you're obfuscating the type for no gain, or even loss in performance. – Aykhan Hagverdili May 02 '23 at 11:41