T&&(doppia e commerciale) in C++11

T&&(doppia e commerciale) in C++11

In questo articolo, abbiamo esplorato l'idea di T&&(doppia e commerciale) in C++11. T&&è stato introdotto per la prima volta nello standard C++ 11 che dichiara un riferimento rvalue.

Riferimenti

Ci sono due riferimenti di valore-

  1. riferimento valore
  2. riferimento valore

"L" sta per sinistra in riferimento lvalue e "R" sta per destra in riferimento rvalue. La cosa da ricordare è che queste sono proprietà di espressioni e non oggetti.

lvalue continua a esistere al di là di un'espressione mentre rvalue finché un'espressione non finisce perché l value è un oggetto mutabile dichiarato sul lato sinistro e destro di un'assegnazione mentre rvalue è un oggetto temporaneo assegnato di un'assegnazione.

In C++ 11, lvalue può associare rvalue.Ex.

T&& a=T();

Codice per comprendere i riferimenti-

#include <iostream>
int main() {
  int a = 1; // a is an lvalue
  int &ref1 = a; // ref1 is a lvalue reference 
  std::cout << "The address of ref1 is same as a: " << &a 

    << ':' << &ref1 << '\n';
  // int &&rref = a; // rvalue reference to type 'int' cannot bind to 

                            // lvalue of type 'int'

  int &&ref2 = 10;
  std::cout << "Value of rref: " << ref2 << '\n';
  // Can't take the address of an rvalue, but can take the address
  // of an rvalue reference variable because it has a name :)
  std::cout << "Address of ref2: " << &ref2 << '\n'; 

  return 0;
}

Uscita-

The address of ref1 is same as x: 0x7ffc7ccd0790:0x7ffc7ccd0790
Value of ref2: 10
Address of ref2: 0x7ffc7ccd0794

Con il codice sopra possiamo avere una piccola idea di ciò che effettivamente lvalue e rvalue fanno riferimento. Possiamo migliorare ulteriormente la nostra conoscenza di riferimento di T&&utilizzandolo in una funzione.

Codice

printR (const std::string& s)  {
    std::cout << "rvalue reference: " << s << '\n';
}
printR (std::string&& str) {
    std::cout << "rvalue reference: " << s << '\n';
}

La prima funzione accetterà qualsiasi argomento sia esso lvalue o rvalue reference, mentre la seconda accetterà solo rvalue eccetto i riferimenti rvalue mutevoli.

Ora chiameremo la funzione quelle funzioni per vedere cosa restituiscono.

Codice

std::string m = "OpenGenus";
printR(m); // calls function #1, taking an lvalue reference
printR("Joe"); // calls function #2, taking an rvalue reference
printR(std::string("Carl")) // function #2 too!

I riferimenti Rvalue ci dicono se la variabile di riferimento è un oggetto temporaneo o permanente.
Di seguito è implementato l'intero programma sopra menzionato in parti-

Codice

#include <iostream>
using namespace std;
string printR (const string& s)  {

    cout << "rvalue reference: " << s << '\n';

}
string printR (string&& s) {

    cout << "rvalue reference: " << s << '\n';

}
int main() {
   string a = "OpenGenus";
   string s1=printR(a); 
   string s2=printR("Joe"); // calls function #2, taking an rvalue reference
   string s3=printR(string("Carl")) ;// function #2 too!
   cout<<s1;
   cout<<s2;
   cout<<s3;
    return 0;
}

Uscita

rvalue reference: OpenGenus
rvalue reference: Joe
rvalue reference: Carl

I riferimenti Rvalue forniscono quanto segue-

  1. Sposta semantica-

L'uso del codice sopra ha il suo effetto collaterale, ma non importa fino a quando non viene utilizzato un valore molto grande che alla fine distingue i riferimenti rvalue e lvalue. Quindi, spostare oggetti di grandi dimensioni ci costa molta più memoria, perché non usiamo qualcosa che utilizza la memoria utilizzata dal valore temporaneo.

Per applicare questo abbiamo bisogno di usare il costruttore di spostamento e l'assegnazione di spostamento che prende il riferimento rvalue e sposta le funzioni come una copia che è utile per eliminare le copie della libreria standard.

Es.

f(f const& a)
{
    this->length = a.length;
    this->ptr = new int[a.length];
    copy(a.ptr, a.ptr + a.length, this->ptr);
}

Ora, se sovraccarichiamo il nostro costruttore-

f(f&& a)
{
    this->length = a.length;
    this->ptr = a.ptr;
    a.length = 0;
    a.ptr = nullptr;
}

Ora, il costruttore di spostamento modifica effettivamente i suoi argomenti, eliminando le sue copie e spostando in modo efficiente il costruttore.

2.Inoltro perfetto-

I riferimenti Rvalue ci consentono di inoltrare argomenti per le funzioni modello.
Le funzioni modello sono quelle funzioni che adattano più di un tipo per aumentare la riutilizzabilità. Es.

template <typename T1, typename A1>
utr<T1> factory(A1& a1)
{
  return unique_ptr<T1>(new T1(forward<A1>(a1)));
}

Proprietà importanti dei riferimenti-

Dalla spiegazione di cui sopra possiamo capire quanto segue -

  1. Lvalue è qualsiasi cosa che abbia un nome.Ex.int a =1 ,
    int &r =a.
    2.Lvalue è un oggetto mutabile che ha un indirizzo di memoria.
    3.Rvalue è un oggetto temporaneo che si trova sul lato destro di un'assegnazione.
    4.Lvakue può essere posizionato su qualsiasi lato dell'incarico a destra oa sinistra di entrambi.

Con questo articolo su OpenGenus, devi avere un'idea completa di T&&(doppia e commerciale) in C++11.