gwarantowane copy elision

gwarantowane copy elision
SY
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 25
1

Dzisiaj wykryłem że guaranted copy elision nie do końca działa (czyli że możesz nie mieć copy,move ctora a i tak będziesz miał return value optimalization).
W C++14 zgodnie z oczekiwaniami to się nie kompiluje, natomiast kompiluje się w C++17:

Kopiuj
#include <stdio.h>
#include <iostream>

class Base{
public:
    Base() 
    {
        std::cout << "Base ctor" << std::endl;
    }
    Base(const Base& base)
    {
        std::cout << "Base copy ctor" << std::endl;
    }
    Base(Base&& base) = delete;
    //Base(Base&& base)
    //{
    //    std::cout << "Base move ctor" << std::endl;
    //}
};

/*Base fun()
{
    Base b;
    return b;
}*/

Base fun2()
{
    return Base();
}

int main()
{
    Base b = fun2();
    return 0;
}

To spoko. Na razie wszystko się zgadza. Ale jak odkomentujesz fun() i użyjesz:

Kopiuj
Base b = fun();

to też powinno być podobnie w C++14 nie kompiluje się a w C++17 kompiluje. Ale niespodzianka, w C++17,20,23 to się nie kompiluje. Czyli quaranted copy elision działa w ograniczonym zakresie tylko dla Return Value Optimalization ale nie już dla Named Return Value Optimalization i tak to trzeba zapamiętać???

Iroh
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 7
1

Wszystko jest wyjaśnione na cppreference - https://en.cppreference.com/w/cpp/language/copy_elision

SY
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 25
0

ok, to tak to można zapamiętać że guaranted copy elision mamy tylko dla RVO ale nie już dla NRVO.

several
  • Rejestracja: dni
  • Ostatnio: dni
4

To jest ciekawy pitfall, więc najpierw odpowiem na pytanie.

ok, to tak to można zapamiętać że guaranted copy elision mamy tylko dla RVO ale nie już dla NRVO

No nie, i dla jednego i drugiego możemy mieć do czynienia z copy elision. Chodzi o to, że copy elision nie zwalnia Cię z konieczności zaimplementowania konstruktorów kopiujących, nawet jeśli potencjalnie nie zostaną użyte. Jak odkomentujesz move ctor i uruchomisz kod gdzie zwracasz z fun()' to i tak jedyny z kontruktorów jaki zostanie zawołany to domyślny w celu inicjalnego utworzenie obiektu https://wandbox.org/permlink/v551FRRbZskB201T. Kopiujące zostaną pominięte tak w C++14 jak i wyższych. Patrz też screenshot niżej.

I teraz wcelu uściślenia, na wszelki wypadek.

wykryłem że guaranted copy elision nie do końca działa

guaranteed copy elision wcale nie jest guaranteed. Chodzi o to, że przed C++17 opisany był zestaw wymogów dla których standard dopuszczał zastosowanie copy elision. W C++17 przy spełnieniu zestawu wymogów copy elision ma być gwarantowane. Dla niektórych wydaje się to oczywiste, ale spotkałem i takich którzy sądzą, że od C++17 już nie muszą się martwić nadmiernym kopiowaniem bo w końcu copy elision jest "gwarantowane", dlatego wolę to wyjaśnić tutaj przy okazji.

screenshot-20250304235921.png

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.