wbrew powszechnej opinii, nie ma gwarancji, że przypisywanie wynik funkcję powracającego obiektu przez wartość dla const odniesienia spowoduje mniej egzemplarzy niż przypisanie go do obiektu samo.
Po przypisaniu wartości r do odwołania do const, kompilator może powiązać odwołanie na jeden z dwóch sposobów Może utworzyć nowy tymczasowy, kopiując wartość rurn i powiązać z nią odniesienie, lub może powiązać odniesienie bezpośrednio z samą wartością runk.
Jeśli kompilator nie jest w stanie wykonać "oczywistej" optymalizacji w celu usunięcia tymczasowego i przeniesienia konstruktora kopiowania dla wartości zwracanej getFoo
, to jakie jest prawdopodobieństwo, że będzie w stanie wykonać bardziej wydajną formę wiązania rwartość do wartości stałej bez tworzenia nowego tymczasowego?
Jednym z powodów użycia referencji do stałych byłoby sprawienie, że funkcja będzie bardziej odporna na potencjalne cięcie.Jeśli typem zwracanym był typ pochodzący od Foo
, to zagwarantowanie, że nie zostanie podzielone odwołanie do referencji stałej dla klasy bazowej, nawet jeśli kompilator wykona obiekt tymczasowy z wartości zwracanej przez funkcję. Kompilator wygeneruje również poprawne wywołanie do destruktora klasy pochodnej , niezależnie od tego, czy destruktor w klasie bazowej jest wirtualny, czy też nie, czy nie jest nim. Dzieje się tak dlatego, że typ utworzonego tymczasowego obiektu jest oparty na typie przypisywanego wyrażenia, a nie na typie inicjowanego odniesienia.
Należy zauważyć, że kwestia tego, jak wiele kopii zwracanej wartości są dokonywane jest całkowicie oddzielony od optymalizacji wartości powrotnej i optymalizacja wartość nazwie powrót. Te optymalizacje odnoszą się do wyeliminowania kopii wyniku rwartości z wartościowania zwrotnego lub nazwanej zmiennej lokalnej do wartości zwracanej funkcji w treści samej funkcji. Oczywiście w najlepszym możliwym przypadku można dokonać optymalizacji wartości zwracanej, a tymczasowy dla wartości zwracanej można wyeliminować, co powoduje, że nie są wykonywane żadne kopie zwróconego obiektu.
Jeśli kompilator powiąza wartość rurnu z odwołaniem do const przez wykonanie kopii, która może obejmować konstruktor kopii, który jest zdefiniowany przez A :: A (const A &), w jaki sposób następowałby poniższy kod? A x = A (parametr); –
@ZheYang: z notatki w starym standardzie: "Oczywiście, jeśli przetwarzana inicjalizacja odwołania jest jedna dla pierwszego argumentu wywołania konstruktora kopiowania, implementacja musi ostatecznie wybrać pierwszą alternatywę (powiązanie bez kopiowania), aby uniknąć nieskończonej rekurencji ". W nowym standardzie ten wybór został usunięty z implementacji. –
Interesujące. Myślę, że to dlatego, że w nowym standardzie mamy teraz konstruktor ruchu, ale w każdym razie może go brakować. –