T&&(doppeltes kaufmännisches Und) in C++11

T&&(doppeltes kaufmännisches Und) in C++11

In diesem Artikel haben wir die Idee von T&&(doppeltes kaufmännisches Und) in C++11 untersucht. T&&wurde erstmals im C++ 11-Standard eingeführt, der eine rvalue-Referenz deklariert.

Referenzen

Es gibt zwei Wertreferenzen-

  1. lvalue-Referenz
  2. rvalue-Referenz

„L“ steht für links in lvalue-Referenzen und „R“ steht für rechts in rvalue-Referenzen. Denken Sie daran, dass dies Eigenschaften von Ausdrücken und nicht von Objekten sind.

lvalue bleibt über einen Ausdruck hinaus bestehen, während rvalue bis ein Ausdruck endet, da lvalue ein veränderliches Objekt ist, das auf der linken und rechten Seite einer Zuweisung deklariert wird, während rvalue ein temporäres Objekt ist, das einer Zuweisung zugewiesen wird.

In C++ 11 kann lvalue rvalue.Ex.

binden
T&& a=T();

Code zum Verstehen von Referenzen-

#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;
}

Ausgabe-

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

Durch den obigen Code können wir uns eine kleine Vorstellung davon machen, was eigentlich lvalue und rvalue referenzieren. Wir können unsere Wissensreferenz von T&&weiter verbessern, indem wir es in einer Funktion verwenden.

Code

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

Die erste Funktion akzeptiert jedes Argument, egal ob Lvalue oder Rvalue-Referenz, während die zweite nur Rvalues ​​außer veränderlichen Rvalue-Referenzen akzeptiert.

Jetzt rufen wir die Funktion diese Funktionen auf, um zu sehen, was sie zurückgeben.

Code

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!

Rvalue-Referenzen sagen uns, ob die Referenzvariable ein temporäres Objekt oder permanent ist.
Unten ist das gesamte oben erwähnte Programm in Teilen implementiert-

Code

#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;
}

Ausgabe

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

Rvalue-Referenzen bieten Folgendes:

  1. Bewegungssemantik-

Die Verwendung des obigen Codes hat seinen Nebeneffekt, aber es spielt keine Rolle, bis wir einen sehr großen Wert verwenden, der schließlich die rvalue- und lvalue-Referenzen unterscheidet. Das Verschieben großer Objekte kostet uns also viel mehr Speicher, warum verwenden wir nicht etwas, das wir verwenden verwendet den Speicher, der vom temporären Rvalue verwendet wird.

Um dies anzuwenden, müssen wir den Bewegungskonstruktor und die Bewegungszuweisung verwenden, die eine rvalue-Referenz und Bewegungsfunktionen wie eine Kopie verwenden, was gut zum Eliminieren von Kopien der Standardbibliothek ist.

Bsp.

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

Wenn wir nun unseren Konstruktor überladen –

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

Jetzt modifiziert der Move-Konstruktor tatsächlich seine Argumente, eliminiert seine Kopien und verschiebt den Konstruktor effizient.

2.Perfekte Weiterleitung-

Rvalue-Referenzen ermöglichen es uns, Argumente für Vorlagenfunktionen weiterzuleiten.
Vorlagenfunktionen sind solche Funktionen, die mehr als einen Typ anpassen, um die Wiederverwendbarkeit zu erhöhen. Bsp.

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

Wichtige Eigenschaften von Referenzen-

Durch die obige Erklärung können wir das Folgende verstehen -

  1. Lvalue ist alles was einen Namen hat.Ex.int a =1 ,
    int &r =a.
    2.Lvalue ist ein veränderliches Objekt mit einer Speicheradresse.
    3.Rvalue ist ein temporäres Objekt, das sich auf der rechten Seite einer Zuweisung befindet.
    4.Lvakue kann auf jeder Seite der Zuweisung rechts oder links platziert werden.

Mit diesem Artikel bei OpenGenus müssen Sie die vollständige Vorstellung von T&&(doppeltes kaufmännisches Und) in C++11 haben.