1. Kann man wirklich annehmen, dass der Compiler RVO anwendet?
Bei einem einigermaßen aktuellen Compiler schon, MSVC 2012 machts z.B.:
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
#include <iostream>
struct blub
{
blub()
{
std::cout << "blub c'tor\n";
}
blub(const blub&)
{
std::cout << "blub copy c'tor\n";
}
~blub()
{
std::cout << "blub d'tor\n";
}
};
class Fabulous
{
blub b;
public:
blub f()
{
return b;
}
};
int main()
{
Fabulous f;
auto x = f.f();
return 0;
}
|
Output:
|
Quellcode
|
1
2
3
4
|
blub c'tor
blub copy c'tor
blub d'tor
blub d'tor
|
In welchen Fällen macht es dann überhaupt noch Sinn, etwas per konstanter Referenz zu übergeben?
RVO bzw. Copy Elision im Allgemeinen (RVO ist nur eine konkrete Art von Optimierung, die auf Copy Elision basiert) funktioniert halt nur in ganz bestimmten Fällen. Bei dem, woran du da denkst, kann der Compiler lediglich unnötige Kopien
temporärer Objekte auslassen (unter der zusätzlichen Bedingung, dass diese nicht schon an eine Referenz gebunden wurden). Spätestens sobald du ein benanntes Objekt übergeben würdest, müsste dieses wieder kopiert werden. Auch darf man nicht vergessen, dass es sich hier um Optimierungen handelt, die der Standard lediglich
erlaubt, nicht aber verlangt. Du kannst von einem modernen Compiler erwarten, dass er es tut, du kannst dich aber im Allgemeinen nicht darauf verlassen.
2. Müsste in meinem Beispiel die letzte Zeile return Robots oder return std::vector<Robot * const>(Robots); heißen oder ist das egal?
Sofern Robots vom Typ std::vector<Robot * const> ist, dürfte das effektiv keinen Unterschied machen, da der Compiler die temporäre Kopie einfach eliden wird...
3. Funktioniert der Lock-Guard überhaupt oder wurde dessen Destruktor zum Zeitpunkt des Kopiervorgangs schon aufgerufen?
Afaik funktioniert das.
4. Gehe ich recht in der Annahme, dass es nicht funktioniert, eine lokale Kopie in der Funktion zu erzeugen und diese als rvalue-Referenz zurückzugeben, da auch rvalue-Referenzen auf lokale Objekte ungültig werden?
Rein Prinzipiell sind rvalue References erstmal einfach nur normale Referenzen wie lvalue References auch. Die Unterschiede kommen bei Dingen wie Overload Resolution und Template Argument Deduction zum tragen. Durch rvalue-References wird es jedenfalls ganz sicher nicht auf magische Weise plötzlich weniger falsch, Referenzen auf lokale Objekte zu returnen...