2014-11-07 14 views
11

Jeśli poprawnie zrozumiem zasady dotyczące czasu istnienia tymczasników, kod ten powinien być bezpieczny, ponieważ czas życia tymczasowego jest długi do końca pełnego wyrażenia. Nie jestem w 100% pewny, że nie ma tu subtelnego problemu, czy ktoś może potwierdzić, że ten wzorzec użycia jest bezpieczny? Wygląda na to, że działa dobrze w klang i gcc.C++ czas istnienia tymczasowców - czy to jest bezpieczne?

#include <iomanip> 
#include <iostream> 
#include <sstream> 

using namespace std; 

ostringstream& make_string_impl(ostringstream&& s) { return s; } 

template<typename T, typename... Ts> 
ostringstream& make_string_impl(ostringstream&& s, T&& t, Ts&&... ts) { 
    s << t; 
    return make_string_impl(std::move(s), std::forward<Ts>(ts)...); 
} 

template<typename... Ts> 
string make_string(Ts&&... ts) { 
    return make_string_impl(ostringstream{}, std::forward<Ts>(ts)...).str(); 
} 

int main() { 
    cout << make_string("Hello, ", 5, " World!", '\n', 10.0, "\n0x", hex, 15, "\n"); 
} 
+3

Wygląda na to, że powinno być dobrze. –

+0

Technicznie jest OK, ale uważam, że okaże się, że jest to mało wydajne. Rozważ właśnie zdefiniowanie konstruktora łańcuchów za pomocą 'operatora <<'. –

+0

@ Cheersandhth.-Alf Zależy jak agresywnie kompilator wstawia. – cdhowie

Odpowiedz

7

Odpowiednia część standardu w §12.2:

12.2.3) obiekty przejściowe są niszczone jako ostatni krok w ocenie pełnej ekspresji (1.9), że (lexically) zawiera punkt, w którym zostały stworzone.

wyjątkiem:

12.2.4) Istnieją dwa konteksty, w których uzupełnienia tymczasowe są niszczone w innym momencie niż do końca pełnej ekspresji. Pierwszy kontekst to wywołanie konstruktu domyślnego w celu zainicjowania elementu tablicy. ... [nie ma zastosowania]

12.2.5) Drugi kontekst dotyczy odniesienia do pliku tymczasowego. Tymczasowy, do którego odwołanie jest związana lub tymczasowy że pełna przedmiotem podobiektu do których odniesienia związany utrzymuje się przez cały okres odniesienia z wyjątkiem:

  • ...

  • tymczasowe powiązanie z parametrem referencyjnym w wywołaniu funkcji (5.2.2) trwa do zakończenia pełnego wyrażenia zawierającego połączenie.

Więc pójdziesz. Tymczasowy stringstream{} jest powiązany z odwołaniem w wywołaniu funkcji, więc trwa aż do zakończenia wyrażenia. To jest bezpieczne.

+0

Dzięki, że wygląda całkiem definitywnie :) – mattnewport

Powiązane problemy