0

I have a question about C++ references, I'm wondering why the following code is invalid:

class NonCopyable {
public:
  NonCopyable() = default;
  NonCopyable(const NonCopyable &) = delete;
  NonCopyable &operator=(const NonCopyable &) = delete;
};

class RefOwner {
public:
  RefOwner(NonCopyable &ref) : ref_(ref) {}
  void assign(NonCopyable &ref) { ref_ = ref; } // <- error: use of deleted function ‘NonCopyable& NonCopyable::operator=(const NonCopyable&)’

protected:
  NonCopyable &ref_;
};

I was expecting that only the reference to the object (so an address) should be copied, not the whole object, so it should be valid.

The same code using a pointer works just fine:

class RefOwner {
public:
  RefOwner(NonCopyable &ref) : ref_(&ref) {}
  void assign(NonCopyable &ref) { ref_ = &ref; } // ok

protected:
  NonCopyable *ref_;
};

I expected these 2 examples to have the same behaviour, but the first one is invalid. Why is that ?

Thanks for your answers.

Adrien
  • 3
  • 1
  • 4
    you cannot assign new values to references, they can only be initialized – codeling Apr 19 '22 at 11:53
  • 2
    Because `ref_ = ref;` does not change what `ref_` refers to, it invokes a copy of `ref` into the object that `ref_` refers to since its initialization. You cannot "rebind" reference variables to other objects – UnholySheep Apr 19 '22 at 11:54
  • You might be looking for [`std::reference_wrapper`](https://en.cppreference.com/w/cpp/utility/functional/reference_wrapper) – Jarod42 Apr 19 '22 at 11:54
  • If you have `NonCopyable nc; RefOwner ro(nc); NonCopyable nc2;`, then `ro.assign(nc2);` would be equivalent to `nc = nc2;` – molbdnilo Apr 19 '22 at 11:57
  • Thanks for the answers, that's clear now! – Adrien Apr 19 '22 at 12:52

1 Answers1

1

I was expecting that only the reference to the object (so an address) should be copied, not the whole object, so it should be valid.

That's not how references work. To assign a reference is to assign the referred object.

I expected these 2 examples to have the same behaviour,

References and pointers are fundamentally different. You should not expect them to behave the same.

but the first one is invalid. Why is that ?

Because you are copy assigning a non-copyable object.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • Well, "fundamentally" is kind of debatable here. If you go to the actual underlying mechanisms of the concepts, they're somewhat comparable, both being non-owning references to a memory location. The API is quite different though. – JHBonarius Apr 19 '22 at 12:02
  • @JHBonarius They are both similar, and different. What I mean is that because they are different, it's never a good idea to assume that their similarity in one regard implies similarity in another regard. If an example with references works differently (or doesn't work) from an example with pointers, that just means that's a case where references and pointers are different. – eerorika Apr 19 '22 at 12:07