2008-11-04 27 views
8

Jestem trochę nowy w C++ i mam kilka pytań, to jest jedna z nich.Parametry funkcji: Kopiuj lub wskaźnik?

Czy jest DOWOLNY powód, gdy używasz funkcji, która przyjmuje jeden lub kilka parametrów, których parametry będą zawsze przechowywane w zmiennej przed wywołaniem funkcji, aby przekazać kopię zmiennej, a nie wskaźnik do zmiennej?

Mówię w kategoriach wydajności. Wydaje mi się, że przesłanie kopii całej struktury zajęłoby więcej zasobów niż tylko wskaźnik (4 bajty).

Odpowiedz

1

odniesienie jest bardziej powszechne lub odniesienie do stałej, jeśli nie będą się zmieniać.

4

Wskaźnik otwiera się na błędy, ponieważ pozwala on zmieniać obiekt. Wskaźniki mogą wynosić 0, co zwykle powoduje awarie, a to stwarza potrzebę testowania dla 0 wskaźników w każdym miejscu, może to być denerwujące. Korzystanie z referencji w C++, jeśli to możliwe, omija oba te problemy.

+0

Dodam, że wskaźniki bez wartości zerowej są jeszcze bardziej irytujące. – tloach

+0

Co to są wskaźniki inne niż 0? – Motti

+0

int * ohoh = new int; usunąć ohoh; cout << ohoh; // wskaźnik zerowy zerowy – MattyT

2

Główne pytanie nie dotyczy wydajności, ale semantyki i tego, czy funkcja modyfikuje dane w strukturze.

Jeśli twoja funkcja modyfikuje strukturę, podanie wskaźnika pozwoli rozmówcy zobaczyć zmienione dane w strukturze. W takim przypadku przekazanie kopii będzie prawdopodobnie błędne, ponieważ twoja funkcja zmodyfikuje kopię, która jest wtedy (prawdopodobnie) odrzucona. Oczywiście możliwe jest, że twoja funkcja modyfikuje dane, ale nie chcesz modyfikacji, w którym to przypadku kopia jest właściwa, aby chronić oryginalne wartości przed zmianami.

Jeśli twoja funkcja nie modyfikuje struktury, nie ma powodu, aby kopiować wartości, ponieważ będą one odczytywane.

Jeśli nie podoba ci się pomysł przekazywania wskaźników do struktur, powinieneś zdobyć trochę praktyki, ponieważ jest to typowy sposób radzenia sobie ze strukturami w C i C++.

Jeśli chodzi o wydajność, to więcej pracy, aby skopiować strukturę, ale jest to dość niewielkie w schemacie rzeczy. Najpierw pamiętaj o semantyce kodu.

4

Unikaj używania pointer.Use stałą odniesienia, jeżeli w parametrze inny właśnie odniesienie do IN OUT parametrów

12

Istnieje kilka sposobów, w którym przekazując kopię może być tańsze niż przechodzącą wskaźnik.

  1. Obiekt jest równy lub mniejszy od wskaźnika. Bezpośredni dostęp do wartości zawsze będzie szybszy niż wyłuskiwanie wskaźnika.
  2. Struktura jest na tyle mała, że ​​można ją umieścić na stosie przez kompilator. W tym przypadku dostęp do wartości w strukturze odbywa się za pomocą indeksowanych trybów adresowania, a nie pośrednich, indeksowanych trybów adresowania. Te pierwsze są generalnie szybsze.

Istnieją inne powody, dla których chcesz przekazać kopię, a nie referencję, a mianowicie twoja funkcja będzie dokonywała zmian w strukturze, które nie będą odbijane z powrotem do rozmówcy. Chociaż ogólnie jest to kiepska praktyka, sprawdzenie wartości parametru według wartości parametru spowoduje, że widok osoby dzwoniącej nie zostanie zmieniony niepoprawnie.

Teraz za część odpowiedzi pewnie nie chcesz słyszeć: na ogół nie robi to wielkiej różnicy!Użyj metody przekazywania parametrów, która najlepiej nadaje się do semantyki Twojego programu. Jeśli później okaże się, że istnieje wąskie gardło wydajności w danym obszarze, skup się na poprawie wydajności. Nie przesadzaj z optymalizacją!

10

Przekazywanie obiektu przez wskaźnik (lub odwołanie) i przekazywanie kopii tego samego obiektu ma inną semantykę. Jeśli chcesz, aby zmiany dokonane na obiekcie zostały odzwierciedlone poza wywołaniem funkcji, które chcesz semantyką odniesienia, w przeciwnym razie potrzebujesz semantyki wartości.

Powszechnie semantyka wartości mogą być wyrażone przez przepuszczenie wartości przez wartość lub const odniesieniu

void value_semantics(my_obj obj); 
void value_semantics(const my_obj& obj); 

Jednakże const droga referencyjna ma pewne wady, jak również zapobiega kilka optymalizacji, kompilator może powodować powodu aliasing issues również dla obiektów z trywialnymi konstruktorami dodatkowy poziom pośredni (odniesienie jest zaimplementowane jako wskaźnik) może przeważyć nad korzyściami uniknięcia kopii.

Aby uzyskać semantykę odniesienia, można wybrać przekazywanie przez odniesienie lub wskaźnik, ponieważ inne już wspomniane referencje są bardziej naturalne niż wskaźniki w C++ (nie trzeba używać adresu operatora &) i jedynym prawdziwą zaletą wskaźników jest to, że chcesz włączyć wartości NULL.

Zasada jest taka, że ​​w przypadku klas nietrywialnych należy przekazywać przez odniesienie do stałych, w przeciwnym razie przez wartość.