2013-06-16 11 views
12

W C++, czy istnieje wydajność przy przekazywaniu typów pierwotnych przez odniesienie zamiast zwracania przez wartość?Jakiekolwiek korzyści związane z wydajnością przy przekazywaniu typów pierwotnych przez odniesienie zamiast zwracania przez wartość?

+1

Prawdopodobnie nie, ale ostatecznie musisz profilować swoją konkretną sytuację, aby naprawdę wiedzieć. –

+0

możliwy duplikat [Jak przekazać obiekty do funkcji w C++?] (Http://stackoverflow.com/questions/2139224/how-to-pass-objects-to-function -in-c) – soon

+0

typy prymitywów @soon! = obiekty. – djechlin

Odpowiedz

1

W tym przypadku może istnieć jakaś niejasna architektura, ale nie jestem świadomy, gdzie powracające typy wbudowane są mniej wydajne niż przekazywanie parametru out przez odniesienie. Zawsze możesz sprawdzić odpowiedni zespół, aby porównać, jeśli chcesz.

8

[...] Czy istnieje korzyść związana z wydajnością polegająca na przekazywaniu typów pierwotnych przez odniesienie zamiast zwracania przez wartość?

Nieprawdopodobne. Przede wszystkim, jeśli nie masz danych z profilera, które dają powody do działania w inny sposób, nie powinieneś martwić się o problemy z wydajnością podczas projektowania programu. Wybierz najprostszy model , a projekt, który najlepiej będzie spełniać komunikacja .

Co więcej, typy pierwotne są zazwyczaj tanie w kopiowaniu, więc jest to mało prawdopodobne, aby stanowiło wąskie gardło w aplikacji. A ponieważ jest to najprostsza opcja i ta, która sprawia, że ​​interfejs funkcji jest najwyraźniejszy, należy podać wartość.

Po prostu patrząc na podpis, jest oczywiste, że funkcja takich jak:

void foo(int); 

nie przechowuje referencję do argumentu (a co za tym idzie, nie będzie działać w takich kwestiach jak zwisające referencje lub wskaźniki), nie zmieni argumentu w sposób widoczny dla osoby dzwoniącej i tak dalej.

Żadne z powyższych można wywnioskować z podpisem funkcji jak:

void f(int&); // May modify the argument! Will it? Who knows... 

lub nawet:

void f(int const&); // May store a reference! Will it? Who knows... 

Poza tym, przechodząc przez wartości mogą nawet zwiększyć wydajność, pozwalając kompilator wykonywać optymalizacje że potencjalne aliasing zapobiegnie.

Oczywiście wszystko to przy założeniu, że faktycznie nie trzeba modyfikować argumentu wewnątrz funkcji w taki sposób, że efekty uboczne dla tego argumentu będą widoczne dla osoby dzwoniącej po powrocie funkcji - lub zapisaniu odniesienie do tego argumentu.

Jeśli tak jest, należy oczywiście przejść przez odniesienie i użyć odpowiedniej kwalifikacji const.

Dla szerszej dyskusji zobacz także this Q&A on StackOverflow.

2

Zasadniczo nie będzie żadnych korzyści związanych z wydajnością, a także mogą wystąpić koszty wydajności. Rozważmy następujący kod:

void foo(const int& a, const int& b, int& res) { 
    res = a + b; 
    res *= a; 
} 

int a = 1, b = 2; 
foo(a, b, a); 

Gdy kompilator napotka funkcji takich jak add() należy założyć, że i res może alias jak w przykładzie rozmowy więc bez globalnych optymalizacje to będzie musiał wygenerować kod, który ładuje, ładunki b, następnie przechowuje wynik a + b do res, następnie ładuje a ponownie i wykonuje mnożenie, przed zapisaniem wyniku z powrotem do res.

Jeśli zamiast tego którą napisał swoją funkcję tak:

int foo(int a, int b) { 
    int res = a + b; 
    res *= a; 
    return res; 
} 

int a = 1, b = 2; 
int c = foo(a, b); 

Następnie kompilator może załadować i B do rejestrów (lub nawet przekazać je bezpośrednio w rejestrach), czy dodatek i rozmnażajcie się w rejestrach i następnie zwróć wynik (który w wielu konwencjach wywołujących może zostać zwrócony bezpośrednio w rejestrze, w którym został wygenerowany).

W większości przypadków rzeczywiście potrzebujesz semantyki w wersji pass/return według wartości foo, a semantyka aliasingowa możliwa w wersji pass/return przez odniesienie nie musi być obsługiwana. Możesz zapłacić prawdziwą karę za wyniki, korzystając z wersji pass/return według wersji referencyjnej.

Chandler Carruth dał dobry talk, który dotknął tego w C++ teraz.

Powiązane problemy