2013-05-03 19 views
11

MającCzy (* i) .member mniej wydajny niż i-> członek

struct Person { 
    string name; 
}; 

Person* p = ... 

Załóżmy, że żaden operatorzy są przeciążone.


Który z nich jest bardziej wydajny (jeśli występuje)?

(*p).namevs.p->name

Gdzieś w głębi mojej głowie słyszę jakieś dźwięki dzwonów, że operator * dereference może stworzyć tymczasową kopię obiektu; czy to prawda?


Tło tego pytania są przypadki tak:

Person& Person::someFunction(){ 
    ... 
    return *this; 
} 

i zacząłem się zastanawiać, czy zmieniając wynik Person* i ostatni wiersz po prostu return this byłoby żadnej różnicy (w wydajności)?

+0

W tym momencie powinieneś dużo bardziej martwić się czytelnością, a ponieważ '->' jest najpopularniejszym cukrem syntaktycznym, '(* i) .m' jest mile widziane w wielu miejscach. Tylko jeśli jakiekolwiek profilowanie wykaże, że może być związany z tym problem, powinieneś zacząć martwić się jego efektywnością. – PlasmaHH

+3

Spodziewam się, że kompilator wygeneruje dokładnie taki sam wynik. Możesz odpowiedzieć sam, skompilować oba kody do asemblera i sprawdzić wyprodukowany kod. – bluehallu

+0

Zadałem to pytanie z powodu * tła * opisanego - wielu podstawowych operatorów zwykle zwraca odwołanie do siebie i widzę bardzo często, że zwracają '* to'; –

Odpowiedz

8

Gdy zwrócisz referencję, jest to dokładnie to samo, co pomijanie wskaźnika, wykluczona semantyka wskaźnika.
Przekazujesz element sizeof(void*), a nie sizeof(yourClass).

Więc kiedy zrobić:

Person& Person::someFunction(){ 
    ... 
    return *this; 
} 

powrót odwołanie i że odniesienie ma taką samą wewnętrzną rozmiar niż wskaźnik, więc nie ma różnicy czasu wykonywania.

samo dotyczy korzystania z (*i).name, ale w tym przypadku należy utworzyć l-value, która została następnie tą samą semantykę jako punkt odniesienia (patrz również here)

+0

To jest dobry punkt dotyczący wielkości zwrotu. Czy możesz wyjaśnić, co wtedy robi '* p'? Wynikiem tego jest osoba i osoba, czyli osoba fizyczna? –

+0

Otrzymujesz wartość "l", która odwołuje się do adresu obiektu, jeśli przeczytam http://stackoverflow.com/questions/11347111/dereferencing-a-pointer-when-passing-by-reference poprawnie i zgodnie z wikipedia: http://en.wikipedia.org/wiki/Value_(computer_science) – Gui13

+0

Interesujące lektury w linkach, dziękuję :) –

9

Nie ma różnicy. Nawet standard mówi, że oba są równoważne, i jeśli istnieje jakikolwiek kompilator, który nie generuje tego samego binarnego dla obu wersji, to jest zły.

+0

To samo dotyczy wbudowanych typów i zdefiniowanych przez użytkownika? –

+3

@KalamarObliwy zakładając, że żaden operator nie przeładowuje, tak. –

+0

A dla standardowych inteligentnych wskaźników ('std :: unique_ptr',' std :: shared_ptr'), przeciążeni operatorzy nadal zachowują się tak samo. – MSalters

1

Każdy dobry kompilator da takie same wyniki. Możesz odpowiedzieć sam, skompilować oba kody do asemblera i sprawdzić wyprodukowany kod.

+2

https://ideone.com/Ovj7ao – BoBTFish

+0

@BoBTFish * voodoo * –

2

Tak, to o wiele trudniejsze do odczytania i typ, tak jesteś znacznie lepiej korzystający z x->y niż (*x).y - ale inne niż wydajność pisania, nie ma absolutnie żadnej różnicy. Kompilator musi jeszcze odczytać wartość x a następnie dodać przesunięcie do y, czy używasz jednej czy innej formie [zakładając brak zabawne przedmioty/zajęcia zaangażowany które zastępują operator-> i operator* odpowiednio, oczywiście]

Z pewnością nie ma żadnego dodatkowego obiektu utworzonego, gdy odwołuje się (*x). Wartość wskaźnika jest ładowana do rejestru w procesorze [1]. to jest to!

Powrót referencji jest zazwyczaj bardziej efektywny, ponieważ zwraca obiekt (zamiast ukrywać) do obiektu, zamiast tworzyć kopię obiektu. W przypadku obiektów, które są większe niż rozmiar wskaźnika, zazwyczaj jest to wygrana.

[1] Tak, możemy mieć kompilator C++ dla procesora, który nie ma rejestrów. Wiem o co najmniej jednym procesorze z Rank-Xerox, który widziałem około 1984 roku, który nie ma rejestrów, był dedykowanym procesorem LiSP i ma po prostu stos dla obiektów LiSP ... Ale są one dalekie od zwykłych w dzisiejszym świecie. Jeśli ktoś pracuje na procesorze, który nie ma rejestrów, proszę nie udzielaj mojej odpowiedzi tylko dlatego, że nie obejmuję tej opcji. Staram się, aby odpowiedź była prosta.

+3

-1 za nieuwzględnianie procesorów bez ... och, czekaj. :) –

Powiązane problemy