Wpis z mikrobloga

Czy jeżeli robię kopię w funkcji to argumenty powinny być zawsze przekazane by value?

void funkcja(std::string str)
{
std::string s = std::move(str);
}

zamiast

void funkcja(const std::string& str)
{
std::string s = str;
}

i analogicznie w konstruktorze?

Konstruktor(std::string str) : s(std::move(str){}
Mam wrażenie, że nikt tak nie robi, a nie widzę wad tego podejścia.
#cpp
  • 11
@vytah: No właśnie o to mi chodzi, że lepiej zrobić kopie + move , to rozwiązuje obie te sytuacje i nie masz duplikowanego kodu.

std::string:
Dostaje l-value to masz copy+move.
Dostajesz r-value to masz constructor+move.

A wersji z const std::string&
Dostaje l-value to masz referencja+kopia.
Dostajesz r-value to masz constructor+kopia(!!!).

Wersja z overloadami
Dostaje l-value to masz referencja+kopia.
Dostajesz r-value to masz constructor+move.
@Gerax9: Mały błąd we wpisie, oczywiście chodzi mi o obiekty wspierające efektywny move(string, shared_ptr), w przypadku obiektów typu "optional<int>" lepiej zrobić overload, albo const referencje.
@Gerax9: Jedno i drugie podejście będzie działało. Jedno i drugie ma swoje wady i zalety. Generalna zasada jest żeby używać const & zamiast kopiowania, ale to jest raczej zalecenie. Jeżeli funkcja ma wziąć wartość parametru na własność w jakiś sposób (np zmienia jego wartość) to kopia może być ok. Przekazywanie przez kopię ogranicza pole manewru użytkownikowi funkcji - cokolwiek nie zrobi i tak finalnie będzie stworzona kopia przy wywołaniu.

Jak funkcja
Wydajność?


@Gerax9: optymalizuję kod jeżeli jest to potrzebne. Wyleczyłem się z optymalizacji każdej linijki kodu. BTW: nie wiem czy wiesz ale przy krótkich stringach (do 22 znaków) oba podejścia są równoważne.

No to czemu nie piszesz w pythonie? Wtedy będzie mniej znaków.


@Gerax9: Bo kodzę w C++.
@BeginEnd:

optymalizuję kod jeżeli jest to potrzebne. Wyleczyłem się z optymalizacji każdej linijki kodu.

Ale to nie jest jakaś specjalnie trudna optymalizacja, tylko po prostu zasada pisania kodu.

BTW: nie wiem czy wiesz ale przy krótkich stringach (do 22 znaków) oba podejścia są równoważne.

Właściwie to 15 znaków + '\0', a przynajmniej tak jest na systemach 64 bitowych, bo wtedy zamiast dwóch wskaźników masz te 16 bajtów.
@Gerax9: podejście z const referencją ma wadę jak przychodzi do konwersji. przekazując const char* stworzysz temporary stringa, którego będziesz kopiował, w podejściu z wartością zmovujesz ten, który powstał przy konwersji.

teoretycznie fajnie by było mieć obie sygnatury. w praktyce idzie się skichać przy 2^n overloadach dla n parametrów.

po to powstał perfect forwarding, żeby miec jeden generyczny overload, ale wtedy witajcie szablony i ich mankamenty.