Wskaźnik a odniesienie

Co byłoby lepszą praktyką przy nadawaniu funkcji zmiennej oryginalnej do pracy:

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 wybrać jednego nad drugim?

Author: Robert Harvey, 2008-09-22

12 answers

Moja zasada to:

Użyj wskaźników, jeśli chcesz wykonać z nimi arytmetykę wskaźnika (np. zwiększyć adres wskaźnika, aby przejść przez tablicę) lub jeśli kiedykolwiek musisz przekazać wskaźnik NULL.

Użyj odniesień w inny sposób.

 266
Author: Nils Pipenbrinck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-31 00:11:49

Naprawdę myślę, że skorzystasz z ustanowienia następującej funkcji wywołującej wytyczne kodowania:

  1. Jak we wszystkich innych miejscach, zawsze bądź const - poprawny.

    • Uwaga: oznacza to, między innymi, że tylko wartości out-values (patrz punkt 3) i wartości przekazywanych przez value (patrz punkt 4) mogą nie posiadać specyfikacji const.
  2. Przekazuje wartość za pomocą wskaźnika tylko wtedy, gdy wartość 0 / NULL jest poprawnym wejściem w bieżącym kontekście.

    • Uzasadnienie 1: Jako rozmówca , widzisz, że cokolwiek mijasz musi być w stanie użytecznym.

    • Uzasadnienie 2: Jak nazywa się, wiesz, że cokolwiek przychodzi jest w stanie użytecznym. W związku z tym nie trzeba sprawdzać wartości NULL ani obsługiwać błędów dla tej wartości.

    • Uzasadnienie 3: uzasadnienie 1 i 2 będzie egzekwowane przez kompilator. Zawsze wyłapuj błędy podczas kompilacji, jeśli możesz.

  3. Jeśli argument funkcji jest wartość wyjściowa, a następnie przekaż ją przez odniesienie.

    • uzasadnienie: nie chcemy łamać punktu 2...
  4. Wybierz "pass by value "zamiast" pass by const reference " 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) do skopiowania.

      Uzasadnienie: unikaj niepotrzebnych kopii.
  5. Uwaga: wystarczająco małe i wystarczająco tanie nie są absolutne odmierzające.
 69
Author: Johann Gerell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:08

To ostatecznie staje się subiektywne. Dyskusja do tej pory jest przydatna, ale nie sądzę, aby istniała na to prawidłowa lub zdecydowana odpowiedź. Wiele zależy od wytycznych stylu i Twoich potrzeb w tym czasie.

Podczas gdy istnieją różne możliwości (czy coś może być NULL) ze wskaźnikiem, największą praktyczną różnicą dla parametru wyjściowego jest wyłącznie składnia. Google ' S C++ Style Guide ( https://google.github.io/styleguide/cppguide.html#Reference_Arguments ), na przykład, nakazuje tylko wskaźniki dla parametrów wyjściowych i zezwala tylko na odwołania, które są const. Rozumowanie polega na czytelności: coś ze składnią wartości nie powinno mieć znaczenia semantycznego. Nie sugeruję, że jest to koniecznie dobre lub złe, ale myślę, że chodzi o to, że to kwestia stylu, a nie poprawności.

 24
Author: Aaron N. Tubbs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-18 11:19:55

Powinieneś przekazać wskaźnik, jeśli chcesz zmodyfikować wartość zmiennej. Nawet jeśli technicznie przekazywanie odniesienia lub wskaźnika jest takie samo, przekazywanie wskaźnika w przypadku użycia jest bardziej czytelne, ponieważ "reklamuje" fakt, że wartość zostanie zmieniona przez funkcję.

 7
Author: Max Caceres,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-22 15:28:12

Pointers Vs. Refereces

Referencje są mniej potężne niż wskaźniki:

1) Po utworzeniu referencji nie można później odwołać się do innego obiektu; nie można jej ponownie odtworzyć. Często odbywa się to za pomocą wskaźników.

2) odwołania nie mogą być NULL. Wskaźniki są często traktowane jako NULL, aby wskazać, że nie wskazują na jakąkolwiek ważną rzecz.

3) Referencja musi być zainicjalizowana po zadeklarowaniu. Nie ma takiego ograniczenia z pointers

Ze względu na powyższe ograniczenia, odniesienia w C++ nie mogą być używane do implementacji struktur danych, takich jak Linked List, drzewo itp. W Javie odniesienia nie mają powyższych ograniczeń i mogą być używane do implementacji wszystkich struktur danych. Referencje posiadanie większej mocy w Javie jest głównym powodem, dla którego Java nie potrzebuje wskaźników.

Referencje są bezpieczniejsze i łatwiejsze w użyciu:

1) bezpieczniej: ponieważ odniesienia muszą być inicjowane, Dzikie odniesienia jak Dzikie wskaźniki są mało prawdopodobne. Nadal możliwe jest posiadanie referencji, które nie odnoszą się do poprawnej lokalizacji

2) łatwiejszy w użyciu: odwołania nie potrzebują operatora dereferencyjnego, aby uzyskać dostęp do wartości. Mogą być używane jak normalne zmienne. operator ' & ' jest potrzebny tylko w momencie zgłoszenia. Również elementy odniesienia do obiektu można uzyskać za pomocą operatora dot ('.'), w przeciwieństwie do wskaźników, w których operator strzałki ( - > ) jest potrzebny do uzyskania dostępu do członków.

Wraz z powyższymi powodami, jest kilka miejsc takich jak argument konstruktora kopiującego, w których wskaźnik nie może być użyty. W konstruktorze kopiującym należy użyć referencji. Podobnie odniesienia muszą być używane do przeciążania niektórych operatorów, takich jak ++.

 6
Author: Yogeesh H T,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-04 06:02:56

Jeśli masz parametr, w którym może być konieczne wskazanie braku wartości, powszechną praktyką jest, aby parametr był wartością wskaźnika i przeszedł w NULL.

Lepszym rozwiązaniem w większości przypadków (z punktu widzenia bezpieczeństwa) jest użycie boost::optional. Pozwala to na przekazywanie opcjonalnych wartości przez odniesienie, a także jako wartość zwracaną.

// Sample method using optional as input parameter
void PrintOptional(const boost::optional<std::string>& optional_str)
{
    if (optional_str)
    {
       cout << *optional_str << std::endl;
    }
    else
    {
       cout << "(no string)" << std::endl;
    }
}

// Sample method using optional as return value
boost::optional<int> ReturnOptional(bool return_nothing)
{
    if (return_nothing)
    {
       return boost::optional<int>();
    }

    return boost::optional<int>(42);
}
 5
Author: Kiley Hykawy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-17 21:53:19

Użyj referencji, gdy możesz, użyj wskaźnika, gdy musisz. Z C++ FAQ: "Kiedy powinienem używać referencji, a kiedy wskaźników?"

 4
Author: RezaPlusPlus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-23 07:37:01

Odniesienie jest wskaźnikiem ukrytym. Zasadniczo można zmienić wartość punktów odniesienia, ale nie można zmienić odniesienia do czegoś innego. Więc moje 2 centy jest to, że jeśli chcesz tylko zmienić wartość parametru przekazać go jako odniesienie, ale jeśli trzeba zmienić parametr, aby wskazać na inny obiekt przekazać go za pomocą wskaźnika.

 3
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-22 15:23:53

Rozważ słowo kluczowe out C#. Kompilator wymaga, aby wywołujący metodę zastosował słowo kluczowe out do dowolnego args, nawet jeśli już wie, czy tak jest. Ma to na celu zwiększenie czytelności. Chociaż przy nowoczesnych Idach jestem skłonny myśleć, że jest to zadanie do podświetlania składni (lub semantycznego).

 3
Author: Daniel Earwicker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-25 09:29:45

Wskaźniki

  • Wskaźnik jest zmienną zawierającą adres pamięci.
  • deklaracja wskaźnika składa się z typu podstawowego, * i nazwy zmiennej.
  • wskaźnik może wskazywać dowolną liczbę zmiennych w życiu
  • Wskaźnik, który obecnie nie wskazuje na poprawną lokalizację pamięci, otrzymuje wartość null (która jest równa zero)

    BaseType* ptrBaseType;
    BaseType objBaseType;
    ptrBaseType = &objBaseType;
    
  • & jest operatorem jednoargumentowym, który zwraca adres pamięci swojego operand.

  • Operator Dereferencing ( * ) jest używany do uzyskania dostępu do wartości przechowywanej w zmiennej, na którą wskazuje wskaźnik.

       int nVar = 7;
       int* ptrVar = &nVar;
       int nVar2 = *ptrVar;
    

Odniesienie

  • Referencja (&) jest jak alias do istniejącej zmiennej.

  • Referencja ( & ) jest jak stały wskaźnik, który jest automatycznie dereferowany.

  • Jest zwykle używany do list argumentów funkcji i wartości zwracanych przez funkcję.

  • Odniesienie musi być zainicjowany podczas tworzenia.

  • Po zainicjowaniu odniesienia do obiektu nie można go zmienić na odniesienie do innego obiektu.

  • Nie możesz mieć odniesień zerowych.

  • Odniesienie do const może odnosić się do const int. Odbywa się to za pomocą zmiennej tymczasowej o wartości const

    int i = 3;    //integer declaration
    int * pi = &i;    //pi points to the integer i
    int& ri = i;    //ri is refers to integer i – creation of reference and initialization
    

Tutaj wpisz opis obrazka

Tutaj wpisz opis obrazka

 3
Author: Saurabh Raoot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-13 12:43:18

Podaj referencję const, chyba że istnieje powód, dla którego chcesz zmienić / zachować zawartość, którą przekazujesz.

Będzie to najbardziej efektywna metoda w większości przypadków.

Upewnij się, że używasz const na każdym parametrze, którego nie chcesz zmieniać, ponieważ nie tylko chroni cię to przed zrobieniem czegoś głupiego w funkcji, ale daje dobre wskazanie innym użytkownikom, co funkcja robi z przekazanymi wartościami. Obejmuje to tworzenie wskaźnika const, gdy chcesz zmienić tylko to, co / align = "left" / ..

 2
Author: NotJarvis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-22 11:43:55

Wskaźniki:

  • można przypisać nullptr (LUB NULL).
  • na stronie wywołania musisz użyć & jeśli twój typ nie jest wskaźnikiem, dokonując wyjaśnień modyfikujesz swój obiekt.
  • wskaźniki mogą być odbite.

Bibliografia:

  • nie może być null.
  • raz związany, nie może się zmienić.
  • rozmówcy nie muszą używać &. Czasami uważa się to za źle, ponieważ musisz przejść do implementacji funkcji, aby sprawdzić, czy Twój parametr jest zmodyfikowany.
 2
Author: Germán Diago,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-29 13:09:06