2

I've noticed a peace of code works even throwing away the ampersand/reference signal.

QWidget* widget;
func(widget);

Do the following expressions mean the same?

func(QWidget* const &widget)
func(QWidget* const widget)

I understand both are pointers that cannot be modified to stuff that can be modified.

An answer focused on the practical effects of both will be more valuable.

KcFnMi
  • 5,516
  • 10
  • 62
  • 136
  • 1
    It might _work, but it also copies `widget` by-value. That copy might be prohibitively costly for non-basic types, though it's possible slightly cheaper for basic types such as pointers. Both have their different uses. – underscore_d Jul 04 '16 at 15:43
  • Interesting, so `func(QWidget* const widget)` might be even better (cheaper). I saw this in the `insert` method of a `QMap`. – KcFnMi Jul 04 '16 at 15:47
  • 1
    Yep, pass-by-value is recommended for built-in types (and, more recently, larger objects, debated for various reasons elsewhere). Passing a reference to a `const` pointer is, pardon the pun, pointless. The only use for a reference here would be a non-`const` one if you wanted to have your function update the pointer in a way the caller can observe, i.e. as an output parameter. – underscore_d Jul 04 '16 at 16:34
  • passing pointers by reference makes sense only when this pointer is modified by function (which is not the case for `const` pointers). Passing pointer by copy is simpler, safer in some cases and cheaper. – Andrei R. Jul 05 '16 at 07:57

2 Answers2

6

Read the definitions right-to-left:

The first means: widget is a reference to a const pointer to a QWidget object

QWidget* const &widget

The second means: widget is a const pointer to a QWidget object

func(QWidget* const widget)

Of course they are not the same.

Both definitions work because references are automatically derenferenced by the compiler.

Mattia F.
  • 1,720
  • 11
  • 21
1

The single ampersand denotes an lvalue reference - a reference to a value that persists beyond the expression you use it in; a value you can take an address of.

The practical consequence are that if you pass an rvalue (e.g. a literal), the code won't compile:

void func_lref(QWidget* const &widget);
void func_val(QWidget* const widget);

void test(QWidget* widget) {
  func_val(widget);  // OK, pass a copy of the widget parameter by value
  func_lref(widget); // OK, pass an l-reference to the widget parameter
  func_val(nullptr); // OK, pass a copy of nullptr by value
  func_lref(nullptr); // won't compile, a literal can't be l-referenced
}
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313