K
EinUnreg schrieb:
Kann man pToInt bedenkenlos verwenden?
Nein. Es bezieht sich auch auf ein nicht mehr existierendes temporäres int-Objekt. Das verhält sich genauso wie bei
int const* foo(int const& x)
{
return &x;
}
int main()
{
int const* p = foo(5*5);
// p ist ein baumelnder/ungültiger Zeiger
}
Allerdings darfst du
int main()
{
int&& t = 5*5;
}
genauso wie
int main()
{
int const& t = 5*5;
}
schreiben, da hier in diesen Fällen die Lebenszeit des temporären Objekts verlängert wird und es so lange am leben bleibt, wie es die Referenz gibt.
Mit && kannst du auch nur Referenzen (Rvalue-Referenzen) erzeugen so ähnlich wie mit & (Lvalue-Referenzen). Allerdings sind die Regeln ein bisschen anders. Solche Referenzen lassen sich immer nur so initialisieren, dass sie sich auf temporäre Objekte oder andere Objekte, für die sich der Nutzer nicht mehr interessiert, beziehen. Man darf also ruhigen Gewissens das Objekt modifizieren, auf das sich eine Rvalue-Referenz bezieht. Das lässt sich prima für eine "Optimierung" von Kopiervorgängen nutzen. Du kannst deiner selbstgeschriebenen Klasse, sofern sinnvoll, neben dem Kopierkonstruktor auch einen sogenannten Movekonstruktor spendieren, der als Parameter eine Rvalue-Referenz auf nicht-const entgegen nimmt: DeineKlasse&&. Da sich diese Referenz ja nur so initialisieren lässt, dass sie sich auf etwas bezieht, was immer verändert werden darf, kannst du theoretisch dem referenzierten Objekt "die Eingeweide" klauen, statt die Eingeweide zu kopieren. Das ist dann sinnvoll, wenn so ein Objekt, logisch gesehen, aus mehreren Teilen besteht und da auch Sachen bei sind, die im Freispeicher alloziert wurden.
Was man auch noch dazu sagen muss, ist, dass es eine besondere Template-Argument-Deduktionsregel gibt, die sich nur auf ein Muster wie T&& bezieht, wobei T vom Compiler bestimmt wird:
template<class T> void foo(T&& x);
int main()
{
int i = 5*5;
foo(5*5); // --> T=int, T&&=int&&
foo(i); // --> T=int&, T&&=int&
}
Hier ist also x nicht immer eine Rvalue-Referenz sondern ggf auch eine Lvalue-Referenz, falls T ein Lvalue-Referenztyp ist. Du magst hier drüber stolpern, aber es hat seinen Nutzen (siehe "perfect forwarding").