C/C++ Flashcards

1
Q

Right value Reference &&
2 main usages
1) Move semantics (Relies the argument is considered by compiler as T&&)
2) Perfect Forwarding (template ONLY) when T&& is lost, recover it so Move semantics can be invoked

Watch out the difference between
int &&
vs template
T &&

A

CONCRETE TYPE RVR:
if a variable is declared as concrete type int &&, then it can only accept R values (constant or temporary objects…i.e. things without a name)

TEMPLATE RVR
if a variable is declared as template type T && then it can accept either R values (constant or temporary objects…i.e. things without a name) or L values (anything with a name)

That is because for foo(T&& arg) the compiler will generate

foo(T & arg) to accept l-value and
foo(T && arg) to accept r-value

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

No name Rule – Applies to Right Value Reference (RVR) ONLY

A

Variables that are declared as rvalue reference can be lvalues or rvalues. The distinguishing criterion is: if it has a name, then it is an lvalue. Otherwise, it is an rvalue.

T&& foo(T && arg) {
T arg2 = arg;
return arg2;
}

T arg3 = foo(T());
here incoming param is declared as RVR, but it has a name ‘arg’ this ‘arg’ is a l-value

here Return Value is declared as RVR, but “return value” has no name, thus the return value is a RVR, thus T(T&&) constructor will be invoked.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

std: :forward(T &a) forward “reference” based on “reference collapsing rules”
std: :forward(T &a) GUARANTEE that the proper foo() is called:

foo(T &&) or foo(T) preserving move sematics OR
foo(T &) for l-value arguments

A
T&& forward(T& a) noexcept
{
  return static_cast(a);
} 

based on type of invocation argument,

  1. T resolves to X, then return X&&
  2. T resolves to X&, then return X& && –> X&
  3. T resolves to X&&, then return X&& && –> X&&

so we can see r-value or RVR is forwarded as RVR
l-value is forwarded as l-value

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Perfect Forwarding == T&& arg + std::forward(arg)

A
void perfect_forwarding_example(T && arg) {
 /* inside function, arg is now a l-value because it has a name */
  /* this recovers the original L/R value property of arg */
  std::forward(t)
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

In function argument declaration,

use T&& if you want to accept either L-value or R-value or RVR

Inside function, use std::forward(arg) if arg is declared as T&& and you want to recover its “move semantics”

A

That is exactly what std::move does

1) declare T&& as argument so it accepts L or R
2) inside use std::forward() to recover RVR

template 
typename remove_reference::type&&
std::move(T&& a) noexcept
{
  /* this two lines does same as std::forward()
  typedef typename remove_reference::type&& RvalRef;
  return static_cast(a);
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly