Jaka byłaby lepsza praktyka przy nadawaniu funkcji oryginalnej zmiennej do pracy z:
unsigned long x = 4;
void func1(unsigned long& val) {
val = 5;
}
func1(x);
lub:
void func2(unsigned long* val) {
*val = 5;
}
func2(&x);
IOW: Czy jest jakiś powód, aby wybierać między sobą?
Odpowiedzi:
Moja ogólna zasada brzmi:
Użyj wskaźników, jeśli chcesz wykonywać z nimi arytmetykę wskaźnika (np. Zwiększając adres wskaźnika, aby przejść przez tablicę) lub jeśli kiedykolwiek będziesz musiał przekazać wskaźnik NULL.
W przeciwnym razie użyj referencji.
źródło
Base* b = new Derived()
)? To wygląda na przypadek, którego nie da się załatwić bez wskaźników.Naprawdę myślę, że skorzystasz na ustanowieniu następujących wskazówek dotyczących kodowania wywoływania funkcji:
Jak we wszystkich innych miejscach, zawsze bądź
const
poprawny.const
specyfikatora.Przekaż wartość przez wskaźnik tylko wtedy, gdy wartość 0 / NULL jest prawidłowym wejściem w bieżącym kontekście.
Uzasadnienie 1: Jako osoba dzwoniąca widzisz, że cokolwiek przekazujesz, musi być w stanie użytecznym.
Uzasadnienie 2: Jak nazywamy , wiesz, że cokolwiek przychodzi, jest w stanie użytecznym. Dlatego dla tej wartości nie trzeba wykonywać kontroli NULL ani obsługi błędów.
Uzasadnienie 3: Wymogi 1 i 2 zostaną wymuszone przez kompilator . Zawsze wychwytuj błędy w czasie kompilacji, jeśli możesz.
Jeśli argument funkcji jest wartością out, przekaż go przez odwołanie.
Wybierz „przekaż przez wartość” zamiast „przekaż przez stałą odniesienia” tylko wtedy, gdy wartość jest POD ( zwykła stara struktura danych ) lub wystarczająco mała (pod względem pamięci) lub w inny sposób wystarczająco tania (pod względem czasu), aby skopiować.
źródło
std::vector<>
.Ostatecznie jest to subiektywne. Dotychczasowa dyskusja jest przydatna, ale nie sądzę, aby na to pytanie była poprawna lub zdecydowana odpowiedź. Wiele zależy od wytycznych stylu i twoich potrzeb w danym czasie.
Chociaż istnieją pewne różne możliwości (niezależnie od tego, czy coś może mieć wartość NULL) ze wskaźnikiem, największą praktyczną różnicą dla parametru wyjściowego jest czysto składnia. Przewodnik po stylu C ++ firmy Google ( https://google.github.io/styleguide/cppguide.html#Reference_Arguments ), na przykład, nakazuje tylko wskaźniki parametrów wyjściowych i dopuszcza tylko odniesienia, które są stałymi. Rozumowanie dotyczy czytelności: coś ze składnią wartości nie powinno mieć semantycznego znaczenia wskaźnika. Nie sugeruję, że to koniecznie jest dobre lub złe, ale myślę, że chodzi tutaj o to, że jest to kwestia stylu, a nie poprawności.
źródło
Powinieneś przekazać wskaźnik, jeśli zamierzasz zmodyfikować wartość zmiennej. Chociaż technicznie przekazanie odwołania lub wskaźnika jest takie samo, przekazanie wskaźnika w twoim przypadku użycia jest bardziej czytelne, ponieważ „reklamuje” fakt, że wartość zostanie zmieniona przez funkcję.
źródło
const
czy nieconst
, ale możesz sprawdzić, czy parametr przeszedł ala&x
vs.x
, i użyj to przekonanie do kodowania, czy parametr może zostać zmodyfikowany. (To powiedziawszy, są chwile, kiedy będziesz chciał przekazaćconst
wskaźnik, więc konwój jest tylko wskazówką. Argumentowanie, że podejrzenie czegoś może być zmodyfikowane, gdy nie będzie, jest mniej niebezpieczne niż myślenie, że nie będzie, kiedy to będzie ....)Jeśli masz parametr, w którym może być konieczne wskazanie braku wartości, powszechną praktyką jest ustawianie parametru jako wartości wskaźnika i przekazywanie wartości NULL.
Lepszym rozwiązaniem w większości przypadków (z punktu widzenia bezpieczeństwa) jest użycie boost :: opcjonalne . Umożliwia to przekazywanie opcjonalnych wartości przez odniesienie, a także jako wartość zwracaną.
źródło
Użyj odniesienia, kiedy możesz, użyj wskaźnika, kiedy musisz. Z C ++ FAQ: „Kiedy powinienem używać referencji, a kiedy powinienem używać wskaźników?”
źródło
Wskaźniki
Wskaźnik, który obecnie nie wskazuje prawidłowej lokalizacji w pamięci, otrzymuje wartość null (czyli zero)
& Jest jednoargumentowym operatorem, który zwraca adres pamięci swojego operandu.
Operator dereferencji (*) służy do uzyskania dostępu do wartości przechowywanej w zmiennej, na którą wskazuje wskaźnik.
Odniesienie
Odwołanie (&) jest jak alias do istniejącej zmiennej.
Odwołanie (&) jest jak stały wskaźnik, który jest automatycznie usuwany z odniesienia.
Jest zwykle używany do list argumentów funkcji i zwracanych wartości funkcji.
Odwołanie musi zostać zainicjowane podczas jego tworzenia.
Po zainicjowaniu odwołania do obiektu nie można go zmienić, aby odwoływał się do innego obiektu.
Nie możesz mieć referencji NULL.
Odwołanie do stałej może odnosić się do stałej. Odbywa się to za pomocą zmiennej tymczasowej o wartości stałej
źródło
Odwołanie jest domyślnym wskaźnikiem. Zasadniczo możesz zmienić wartość, na którą wskazują punkty odniesienia, ale nie możesz zmienić odniesienia, aby wskazywało na coś innego. Więc moje 2 centy są takie, że jeśli chcesz tylko zmienić wartość parametru, przekaż go jako odniesienie, ale jeśli musisz zmienić parametr, aby wskazywał na inny obiekt, przekaż go za pomocą wskaźnika.
źródło
Zastanów się nad słowem kluczowym C #. Kompilator wymaga, aby wywołujący metodę zastosował słowo kluczowe out do wszystkich argumentów out, nawet jeśli już wie, czy są. Ma to na celu zwiększenie czytelności. Chociaż w przypadku nowoczesnych IDE skłonny jestem myśleć, że jest to zadanie do podświetlania składni (lub semantycznych).
źródło
Przekaż const const, chyba że istnieje powód, dla którego chcesz zmienić / zachować przekazywaną zawartość.
W większości przypadków będzie to najbardziej wydajna metoda.
Upewnij się, że używasz const dla każdego parametru, którego nie chcesz zmieniać, ponieważ to nie tylko chroni cię przed zrobieniem czegoś głupiego w funkcji, ale daje dobre wskazanie innym użytkownikom, co funkcja robi z przekazanymi wartościami. Obejmuje to utworzenie wskaźnika stałej, gdy chcesz tylko zmienić to, na co wskazywałeś ...
źródło
Wskaźniki:
nullptr
(lubNULL
).&
jeśli typ nie jest samym wskaźnikiem, co wyraźnie modyfikuje obiekt.Bibliografia:
&
. Jest to czasami uważane za złe, ponieważ musisz przejść do implementacji funkcji, aby sprawdzić, czy parametr został zmodyfikowany.źródło
Odwołanie jest podobne do wskaźnika, z tym wyjątkiem, że nie trzeba używać prefiksu ∗, aby uzyskać dostęp do wartości, do której odwołuje się odwołanie. Ponadto nie można utworzyć odwołania do innego obiektu po jego inicjalizacji.
Odnośniki są szczególnie przydatne do określania argumentów funkcji.
Aby uzyskać więcej informacji, zobacz „A Tour of C ++” autorstwa „Bjarne Stroustrup” (2014) strony 11–12
źródło