2014-07-03 14 views
5

Współpracownik napisał następujący kod, który, jestem przekonany, jest błędny.Jaka jest terminologia dla tego użycia konstruktora?

chcę wyjaśnić problemy do niego, ale nie wiem właściwego terminu, więc nie mogę znaleźć odnośniki do wspierania mojej pozycji:

jego kod:

BSTR someString = _bstr_t(L"Hello World"); 

Dlaczego Myślę, że to jest złe: Wierzę, że _bstr_t(L"Hello World"); dzwoni do konstruktora dla _bstr_t i tworzy tymczasową zmienną tymczasową tego typu. Ta tymczasowa zostanie automatycznie usunięta, a jej przestrzeń tekstowa zwolniona, natychmiast po tym wierszu kodu (po punkcie z średnikiem).
To sprawi, że someString wskaże pamięć, która została zwolniona.

Pytania:
Jaki jest właściwy termin dla tego połączenia z konstruktorem?

Czy możesz wskazać odniesienia/terminy/strony opisujące szczegółowo zastosowanie?

Czy istnieje termin dla tymczasowego obiektu _bstr_t?
Chyba nazwałbym to "anonimową zmienną tymczasową", ale nie wiem, czy jest to technicznie poprawne.

(lub może jestem całkowicie błędne w mojej analizie .... jeśli tak, to chciałbym wiedzieć)


Dla wyjaśnienia:

_bstr_t is a C++ class, powszechnie używane przez Microsoft do zawijania ich typu BSTR, więc ma konstruktory/destruktory/operatory, itp.

BSTR jest typedef dla tylko WCHAR*, więc nie ma żadnej logiki. To tylko głupia wskazówka.

Odpowiedz

3

Kod w pytaniu

BSTR someString = _bstr_t(L"Hello World"); 

robi conversion constructor call która tworzy instancję bstr_t używając przeszedł wchar_t[]. To samo w sobie jest w porządku. Na przykład jeśli chcesz wywołać funkcję przyjmującą BSTR i przekazać ciąg dosłowne tam można łatwo to zrobić:

someFunction(_bstr_t(L"Hello World")); // OKAY 

i to byłoby w porządku, ponieważ tymczasowe przetrwa do końca całego rachunku która kończy się tam, gdzie znajduje się średnik (tak działają tymczasowe C++).

Jednak kod ten nie jest w porządku, ponieważ instancja _bstr_t jest następnie wykorzystywany do wystąpienia instancji BSTR (za pomocą operatora konwersji w klasie bstr_t), który żyje dłużej niż tymczasowy (tymczasowy jest niszczony w średnikiem i BSTR wskaźnik someString żyje znacznie dalej). Pojawia się więc zwisający wskaźnik BSTR, który prowadzi do niezdefiniowanego zachowania. Może nawet wyglądać, jeśli stertka OLE zdecyduje się zachować pamięć używaną dla łańcucha zamapowanego w przestrzeń adresową procesu.

class _bstr_t dostarczany jest z realizacji (comutil.h plik w Windows SDK), dzięki czemu można wkraczać do kodu z debuggera i zobaczyć, że istnieje jedna SysAllocString() wezwanie gdy tworzony jest tymczasowy, a następnie jeden SysFreeString() wezwanie, gdy jest zniszczona a to drugie dzieje się zanim kod przejdzie do następnego wiersza. Dlatego obiekt łańcucha w sterty OLE jest deallocated zanim kod przejdzie do następnej linii i wskaźnik zwisa natychmiast po danym kodzie. Sądzę, że wystarczyłoby to przekonać nawet najbardziej sceptyczną osobę.

Tak, masz rację, że kod jest błędny. Poprawny kod to:

_bstr_t someString(L"Hello World"); 
+0

Dzięki, termin * "konstruktor konwersji" * jest tym, czego szukałem. – abelenky

5

Masz rację.

A BSTR jest typedef dla wchar_t *, a CComBSTR/_bstr_t ma nie konwertujący operator na wchar_t *.

Tym samym przydzielono tymczasowe _bstr_t, wskaźnik do jego początku jest przypisany do someString za pośrednictwem operatora konwersji, a obiekt jest zwalniany, gdy wychodzi poza zasięg. Następnie dostajesz zwisający wskaźnik.

Można użyć

_bstr_t someString ("Hello World"); 

zamiast, lub nawet _bstr_t someString = "Hello, World";.

+0

Cieszę się, że się zgadzasz. Mój problem dotyczy "zakresu". Zwykle uważam, że zasięg obiektu jest nawiasowy; od '{' aż do dopasowania '}'. Ale tutaj nie ma nawiasów ... więc co dokładnie określa tymczasowy "_bstr_t'" zakres "? – abelenky

+2

@abelenky: Nie jestem adwokatem języka - może możesz zadać to dokładne pytanie tutaj, na SO, ludzie chętnie odpowiedzą. Jestem pewien, że destruktor jest wywoływany po przypisaniu. W przeciwieństwie do 'const _bstr_t & someString =" Hello, World "', który wywołuje konstruktor kopiowania i którego zasięg jest ograniczony za pomocą nawiasów. –

+1

@abelenky: Istotne: http://stackoverflow.com/questions/3041959/life-scope-of-temporary-variable –

Powiązane problemy