copy elision

0

Kiedy robie sobię w funkcji kontener tylko po to, żeby go zwrócić to unikam niepotrzebnego kopiowana tego obiektu, bo copy elision się tym zajmie, racja? Czy mogę być tego pewien?

1

Z tego co wiem "raczej acz niekoniecznie"

http://en.cppreference.com/w/cpp/language/copy_elision

Copy elision is the only allowed form of optimization that can change the observable side-effects. **Because some compilers do not perform copy elision in every situation where it is allowed (e.g., in debug mode), programs that rely on the side-effects of copy/move constructors and destructors are not portable. **

1

Standard nie wymusza na kompilatorze wykonania copy elision, natomiast wymusza przenoszenie obiektu (zamiast kopiowania) jeśli taka operacja jest dostępna, a z jakiegoś powodu kompilator nie zrobił copy elision.

Za The C++ Standard Library 2nd edition:

You don’t have to and should not move() return values. According to the language rules, the standard specifies that for the following code:

X foo()
{
    X x;
    ....
    return x;
}

the following behaviour is guaranteed:
• If X has an accessible copy or move constructor, the compiler may choose to elide the copy. This is the so called (named) return value optimization ((N)RVO), which was specified even before C++11 and is supported by most compilers.
• Otherwise, if X has a move constructor, x is moved.
• Otherwise, if X has a copy constructor, x is copied.
• Otherwise, a compile-time error is emitted.

0

Praktyka jednak pokazuje, ze gcc sobie dobrze z tym radzi, mam racje? Chociaż z drugiej strony, nawet jeśli czasami zawiedzie, to move constructor tak czy siak jest wystarczająco szybki. Właściwie bardzo niewiele wolniejszy.

2
pingwindyktator napisał(a):

Zastanawiało mnie tylko, czy są jakieś magiczne sytuacje, w których copy elision nie może zostać uruchomione z jakiegoś konkretnego powodu, a nie z powodu widzimisie kompilatora.

Kompilator może nie być w stanie zastosować copy elision np. gdy funkcja ma wiele ścieżek wykonania z których każda zwraca inny obiekt albo gdy rzucamy kilka wyjątków z funkcji.

Warto dodać, że standard definiuje, że w przypadku gdy warunki do zadziałania copy elision są spełnione ale kompilator z dowolnej przyczyny nie zastosował tej optymalizacji to wtedy musi nastąpić dwu fazowa overload resolution. Najpierw szukany jest move constructor, jeśli nie uda się go znaleźć to następuje kopiowanie.
Ciekawostka: Scott Meyers w Effective morden C++ odnośnie tej sytuacji napisał, że w przypadku RVO zwracany wartość musi zostać potraktowana jako r-value (powołuje się w tym miejscu na standard, niestety bez podania paragrafu ; <). Imho, to jest nie jest zgodne z prawdą standardem (§ 12.8 [32]). Jest tak jak napisałem powyżej.

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