unique_ptr zwracany z funkcji

0

Cześć :)

Załóżmy, że mam taką funkcję:

std::pair<std::unique_ptr<Matrix>, std::unique_ptr<Matrix>> decomposeMatrix( const Matrix& toDecompose){

std::unique_ptr<Matrix> first = std::make_unique( /* JAKOS TAM DEKOMPONUJ toDecompose);
std::unique_ptr<Matrix> second = std::make_unique( /* JAKOS TAM DEKOMPONUJ toDecompose);

return std::make_pair<std::unique_ptr<Matrix>, std::unique_ptr<Matrix> >( first, second);
}

  1. Jak widać nasza funkcja ma za zadanie zdekomponować macierz pobraną jako argument. I teraz ponieważ te obiekty mogą być bardzo duże nie możemy sobie pozwolić na zwracanie przez wartość, aby uniknąć kopiowania ( zapominamy na chwilę o RVO/NRVO). W takim razie, czy to co zaprezentowałem jest ok? Tzn. zwracanie unique_ptr. Czy to jest ok? Czy lepiej zwracać RAW Pointer typu Matrix*?
    Mówiąc ogólnie:
    Nie mam doświadczenia w programowaniu komercyjnym i nie wiem czy takie cos to jest WTF czy też nie. Dlatego też pytanie jest- jak zrobić to najlepiej?

  2. Dobrze myślę, że przy takiej postaci funkcji wywołane będa move konstruktory dla std::unique_ptr?

0

Przecież to wskaźnik, może poczytaj o tym unique_ptr bo zamierzasz używać a kompletnie tego nie rozumiesz.
Z macierzami radzę zastosować Copy-On-Write

0

No przecież wiem, że to jest wskaźnik. Jednak czym innym jest zwracanie RAW wskaźnika a czym innym unique_ptr. Nie wiem na jakiej podstawie wysnuwasz, że nie wiem, że to wskaźnik skoro treść mojego postu wskazuje na to, że jednak wiem co to wskaźnik. Ale najlepiej nie odpowiedzieć na pytania.

Czekam na jakąś inną odpowiedź.

0

No więc pytanie jest takie:

W programowaniu korporacyjnym ( w takim kodzie, który się oddaje na zewnątrz) jest tendencja żeby opakowywać wskaźniki w unique_ptr/shared_ptr ( i tak, wiem że to są smart wskaźniki, tak wiem czym one się różnią)? Tzn. Tak jak tu:
Zamiast zwracać RAW wskaźnik zwracać inteligenty.
Pobierać zamiast przez wskaźnik poprzez inteligentny...
etc...

P.S. Wiem co to RAW wskaźnik.

1
  1. Przeczytaj http://herbsutter.com/2013/05/30/gotw-90-solution-factories/ . Szczególnie punkt 4. Nie sugeruj się tytułem.

  2. unique_ptr nie ma konstruktora kopiującego. Więc albo przenoszący albo kosntrukcja z czystego wskaźnika.

PS.

Jak już to:

auto first = std::make_unique(JAKOS_TAM_DEKOMPONUJ(toDecompose));
auto second = std::make_unique(JAKOS_TAM_DEKOMPONUJ(toDecompose));

A jeszcze lepiej

auto first =  JAKOS_TAM_DEKOMPONUJ(toDecompose)
auto second = JAKOS_TAM_DEKOMPONUJ(toDecompose)

gdzie matrix ma zaimplementowany move constructor. Wtedy nie będzie zbędnego kopiowania.

0
C napisał(a):

Nie wiem na jakiej podstawie wysnuwasz, że nie wiem, że to wskaźnik skoro treść mojego postu wskazuje na to, że jednak wiem co to wskaźnik. Ale najlepiej nie odpowiedzieć na pytania.
Jawnie wskazuje na to pytanie:

C napisał(a):
  1. Dobrze myślę, że przy takiej postaci funkcji wywołane będa move konstruktory dla std::unique_ptr?
    Co cię obchodzi w jaki sposób zostanie przekazany ten wskaźnik? Jeżeli już obchodzi to prawie każde IDE z obecnego tysiąclecia po jednym kliku przeniesie cię do deklaracji tej klasy - więc sobie zanotuj jak to się robi.
0

@nalik dziękuję- o to chodziło :)

@_13th_Dragon ucz się jak należy odpowiadać.

1
  1. Owszem, istnieje tendencja zwracania / używania smart-pointers zamiast raw pointers. Powodów ku temu jest wiele, jednak najważniejsze z nich to:
    1.1. kod jest nieco czystszy, brak brzydkich delete
    1.2. nikła szansa memory leak, buffer overflow
    1.3. używając smart-pointers definiujemy jednoznacznie jak ze wskaźnikiem postąpić ma ktoś, komu mu go dajemy. Wyobraź sobie funkcję
    int **create_matrix (size_t n, size_t m);
    W jaki sposób mam się zachować, jeśli chcę wywołać tę funkcję? Mam ten wskaźnik poźniej usunąć czy nie? A może dopiero za 2 minuty będę mógł go usunąć, bo wątek logger go musi zapisać gdzieś?
    Dużym problemem jest właśnie fakt, czy jest się pointer observer czy pointer owner. smart-pointers rozwiązują te problemy w oczywisty sposób.

  2. W jaki sposób najlepiej zwrócić coś w przypadku tego typu funkcji? Zwracanie raw-pointer jest głupie, to już wiesz. Jeśli funkcja zachowywać ma się jak "utworze coś i to oddaje", to "zapominanie o RVO" jest bardzo nie ma miejscu. Zwracać powinieneś obiekt via value bo standard zapewnia Ci copy elision - nie będzie ani żadnego kopiowania, ani przenoszenia (12.8.31 i niżej). Jeśli copy elision nie zadziała (bo nie zostaną spełnione warunki), to na tak zwracanej wartości wykonywany jest move ctor. Jeśli i to się nie uda - np nie ma odpowiedniego konstruktora - dopiero wtedy obiekt jest kopiowany.

1

@pingwindyktator
również dziękuję :)
Trafiłeś w punkt ;)

0

Czyli to ja dokładnie trafiłem w punkt - należało poczytać na temat unique_ptr w dokumentacji - tam cała informacja zawarta w jednym miejscu. Zamiast tego dziękujesz za każdą informacje szczątkową którą ci ktoś tu poda.

1

Nieprawda.
No chyba autor tematu wie, kto najlepiej zrozumiał jego intencje. Że też muszę takie rzeczy tłumaczyć...

0

Podają ci informacje z dokumentacji na temat unique_ptr a ty dziękujesz, kto najlepiej zrozumiał będziesz mógł ocenić dopiero po przeczytaniu dokumentacji.
O ile intencją nie było: - nie czytanie dokumentacji za wszelką cenę.

3

Nie mam doświadczenia w programowaniu komercyjnym i nie wiem czy takie cos to jest WTF czy też nie. Dlatego też pytanie jest- jak zrobić to najlepiej?

Wskaż mi miejsce, gdzie pisze o tym w dokumentacji.

2

Swoją drogą - ja bym skłaniał się ku takiemu rozwiązaniu:

typedef std::array matrix_t;

template <typename T, size_t n, size_t m>
matrix_t<T, n, m> decompose_matrix (const matrix_t<T, n, m> &matrix);

1 użytkowników online, w tym zalogowanych: 0, gości: 1