Czy powinniśmy przekazać współdzielony PST według referencji czy wartości?

Gdy funkcja przyjmuje shared_ptr (z boost lub C++11 STL), czy przekazujesz ją:

  • Autor: const reference: void foo(const shared_ptr<T>& p)

  • Lub według wartości: void foo(shared_ptr<T> p) ?

Wolałbym pierwszą metodę, ponieważ podejrzewam, że będzie szybsza. Ale czy to naprawdę warto, czy są jakieś dodatkowe problemy? Czy mógłby Pan podać powody swojego wyboru lub, jeśli sprawa, dlaczego uważa pan, że to nie ma znaczenia?
Author: Olivia Stork, 2010-07-22

8 answers

To pytanie zostało omówione i udzielone przez Scotta, Andrei i Herba podczas zadaj nam cokolwiek sesja w C++ i poza 2011. Oglądaj z 4min 34sec na shared_ptr wydajność i poprawność .

Krótko mówiąc, nie ma powodu, aby przekazywać wartość, chyba że celem jest współwłasność obiektu (np. pomiędzy różnymi strukturami danych lub między różnymi wątkami).

Chyba, że możesz przenieść-zoptymalizować to, jak wyjaśnił Scott Meyers w dyskusja wideo podlinkowane powyżej, ale to jest związane z rzeczywistą wersją C++ można użyć.

Duża aktualizacja tej dyskusji miała miejsce podczas GoingNative 2012 panelu interaktywnego konferencji : zapytaj nas o cokolwiek! które warto obejrzeć, zwłaszcza z 22:50.

 169
Author: mloskot,
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-06-24 18:00:47

Oto herb Sutter ' s take

Wytyczna: nie przekazuj inteligentnego wskaźnika jako parametru funkcji, chyba że chcesz używać lub manipulować samym inteligentnym wskaźnikiem, na przykład udział lub przeniesienie własności.

Wytyczna: wyrażenie, że funkcja będzie przechowywać i dzielić własność obiekt heap za pomocą parametru shared_ptr.

Wytyczna: użyj a non - const shared_ptr & parametr tylko do modyfikacji shared_ptr. Użyj a const shared_ptr & as a parametr tylko wtedy, gdy nie jesteś pewien, czy lub nie będziesz wziąć kopię i współwłasność; w przeciwnym razie użyj widżetu* zamiast tego (lub jeśli nie nullable, widżet&).

 59
Author: acel,
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-10-04 21:23:20

Osobiście użyłbym const referencji. Nie ma potrzeby zwiększania liczby referencji tylko po to, aby ponownie ją zmniejszyć w celu wywołania funkcji.

 49
Author: Evan Teran,
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-16 18:44:56

/ Align = "left" / Jeśli chcesz go przechowywać, powiedzmy w jakimś pojemniku, ref. licznik będzie automatycznie zwiększany przez operację kopiowania.

 29
Author: Nikolai Fetissov,
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
2010-07-22 15:54:46

Uruchomiłem poniższy kod, raz z foo Biorąc shared_ptr przez const& i ponownie z foo Biorąc shared_ptr przez wartość.

void foo(const std::shared_ptr<int>& p)
{
    static int x = 0;
    *p = ++x;
}

int main()
{
    auto p = std::make_shared<int>();
    auto start = clock();
    for (int i = 0; i < 10000000; ++i)
    {
        foo(p);
    }    
    std::cout << "Took " << clock() - start << " ms" << std::endl;
}

Korzystanie z VS2015, X86 release build, na moim procesorze intel Core 2 quad (2.4 GHz)

const shared_ptr&     - 10ms  
shared_ptr            - 281ms 

Wersja copy by value była o rząd wielkości wolniejsza.
Jeśli wywołujesz funkcję synchronicznie z bieżącego wątku, wybierz wersję const&.

 14
Author: tcb,
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-08-26 14:16:48

Od C++11 powinieneś wziąć go przez wartość nad const& częściej niż mogłoby się wydawać.

Jeśli bierzesz STD:: shared_ptr (zamiast bazowego typu T), robisz to, ponieważ chcesz coś z nim zrobić.

Jeśli chcesz skopiować gdzieś , bardziej sensowne jest zabranie go przez copy, a std::przenieś go wewnętrznie, zamiast wziąć go przez const&, a następnie skopiować. Dzieje się tak dlatego, że pozwalasz rozmówcy na opcję w włącz std:: przenieś shared_ptr podczas wywoływania funkcji, zachowując w ten sposób zestaw operacji przyrostowych i przyrostowych. Albo i nie. Oznacza to, że wywołujący funkcję może zdecydować, czy potrzebuje std::shared_ptr po wywołaniu funkcji i w zależności od tego, czy się przesunie, czy nie. Nie jest to osiągalne, jeśli przejdziesz przez const&, a zatem najlepiej jest wziąć go według wartości.

Oczywiście, jeśli wywołujący potrzebuje swojego shared_ptr na dłużej (więc nie może std:: move it) i nie chcesz tworzyć zwykłej kopii w funkcji (powiedzmy, że chcesz słaby wskaźnik lub tylko czasami chcesz go skopiować, w zależności od jakiegoś warunku), wtedy const& może być nadal preferowany.

Na przykład, powinieneś zrobić

void enqueue(std::shared<T> t) m_internal_queue.enqueue(std::move(t));

Over

void enqueue(std::shared<T> const& t) m_internal_queue.enqueue(t);

Ponieważ w tym przypadku zawsze tworzysz kopię wewnętrznie

 7
Author: Cookie,
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-03-21 12:26:18

Nie znając kosztu czasu operacji kopiowania shared_copy gdzie jest inkrement i dekrement atomowy, cierpiałem na znacznie większy problem z użyciem procesora. Nigdy nie spodziewałem się, że przyrost atomowy i spadek może wymagać tak dużych kosztów.

Po moim wyniku testu, int32 przyrost atomowy i zmniejszanie trwa 2 lub 40 razy niż przyrost i zmniejszanie niematomiczne. Mam go na 3GHz Core i7 z Windows 8.1. Pierwszy wynik wychodzi, gdy nie występuje spór, drugi, gdy duża możliwość występuje spór. Mam na uwadze, że operacje atomowe są w końcu blokadą sprzętową. Zamek to zamek. Złe do wydajności, gdy występuje niezgodność.

Doświadczając tego, zawsze używam byref (const shared_ptr&) niż byval (shared_ptr).

 1
Author: Hyunjik Bae,
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-04-17 23:27:04

Shared_ptr nie jest wystarczająco duży, ani jego konstruktor\destructor nie wykonuje wystarczająco dużo pracy, aby nie było wystarczająco dużo narzutu z kopii, aby dbać o wydajność pass by reference vs pass by copy.

 -4
Author: stonemetal,
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
2010-07-22 17:09:08