2009-05-04 13 views
9

Dlaczego nie można napisać kompilatora, który zarządza, co musi być zarządzane w kodzie C++ (to znaczy, aby było "zgodne z CLR")?Dlaczego C++ wymaga "zarządzania" modyfikacjami językowymi?

Może z pewnym kompromisem, jak zabranie nieważnych wskaźników w niektórych sytuacjach itp. Ale wszystkie te dodatkowe słowa kluczowe itp. W czym problem musi zostać rozwiązany przez te dodatki?

Mam swoje przemyślenia na temat niektórych aspektów i tego, co może być trudne do rozwiązania, ale dobre solidne wyjaśnienie byłoby bardzo cenne!

Odpowiedz

12

Nie zgadzam się z dotychczasowymi odpowiedziami.

Głównym problemem do zrozumienia jest to, że kompilator C++ tworzy kod, który jest odpowiedni dla bardzo niemy środowiska. Nawet nowoczesny procesor nie wie o wirtualnych funkcjach, piekle, nawet funkcje są rozciągliwe. Procesor naprawdę nie dba o to, że kod obsługi wyjątków służący do rozwijania stosu znajduje się poza jakąkolwiek funkcją, na przykład. Obsługa procesorów w sekwencjach instrukcji, z przeskokami i zwrotami. Funkcje z pewnością nie mają nazw w odniesieniu do procesora.

W związku z tym wszystko, co jest potrzebne do obsługi koncepcji funkcji, umieszczane jest przez kompilator. Na przykład. vtables to tylko tablice o odpowiednim rozmiarze, z odpowiednimi wartościami z punktu widzenia procesorów. __func__ kończy się jako ciąg bajtów w tabeli smyczkowy, ostatni z których jeden jest 00.

Teraz nie ma nic, że mówi, że środowisko docelowe musi być głupi. Możesz zdecydowanie celować w JVM. Ponownie kompilator musi wypełnić to, co nie jest oferowane natywnie. Brak surowej pamięci? Następnie przydziel dużą tablicę bajtów i użyj jej zamiast niej. Bez surowych wskazówek? Po prostu użyj liczb całkowitych do tej wielkiej tablicy bajtów.

Głównym problemem jest to, że program C++ wygląda całkiem nierozpoznawalnie ze środowiska hostingowego. JVM nie jest głupia, wie o funkcjach, ale oczekuje, że będą członkami klasy. Nie spodziewa się, że mają one w swoich nazwach < i >. Możesz to omijać, ale to, na czym skończysz, to po prostu łamanie nazw. W przeciwieństwie do dzisiejszego maniaka nazw tego rodzaju wymazywanie nazw nie jest przeznaczone dla łączników C, ale dla inteligentnych środowisk. Tak więc jego silnik refleksyjny może przekonać się, że istnieje klasa c__plus__plus z funkcją składową __namespace_std__for_each__arguments_int_pointer_int_pointer_function_address i to nadal jest dobry przykład. Nie chcę wiedzieć, co się stanie, jeśli masz ciągi znaków do odwracania iteratorów.

Odwrotnie jest w sumie dużo łatwiej. Niemal wszystkie abstrakcje innych języków można wymasować w C++. Zbieranie śmieci? To jest już dozwolone w C++ dzisiaj, więc możesz to wspierać nawet dla void*.

Jedną z rzeczy, do której jeszcze nie dotarłem, jest wydajność. Emulacja surowej pamięci w tablicy wielobajtowej? To nie będzie szybkie, szczególnie jeśli włożysz w nie podwójne. Możesz grać dużo sztuczek, aby przyspieszyć, ale za jaką cenę? Prawdopodobnie nie dostaniesz komercyjnie opłacalnego produktu. W rzeczywistości możesz używać języka, który łączy najgorsze części C++ (wiele nietypowych zachowań zależnych od implementacji) z najgorszymi częściami VM (wolno).

4

Istniejący prawidłowy kod, tj. Kod napisany zgodnie ze standardem C++, nie może zmienić jego zachowania w sposób nieumyślny.

1

Qt framework to prawie to. To znaczy. ma inteligentne wskaźniki, które automatycznie ustawiają się na null, gdy obiekt, na który wskazują, jest zniszczony. I nadal jest to natywny C++, po przeanalizowaniu przez moc (kompilator obiektów meta).

1

Myślę, że to dlatego, że dodanie funkcji kodu zarządzanego do C++ spowodowałoby spowolnienie C++, a kompilator byłby bardziej złożony. Tak bardzo, że C++ straciłoby to, na co zostało zaprojektowane. Jedną z przyjemnych rzeczy w C++ jest to, że jest to przyjemny język do pracy, jest wystarczająco niski, a jednocześnie dość przenośny. I prawdopodobnie właśnie to Komitet Standardowy C++ planuje tak pozostać. W każdym razie nie uważam, że C++ może kiedykolwiek być w pełni "zarządzany", ponieważ oznaczałoby to, że programy napisane w C++ wymagają wykonania VM. Jeśli tak, to dlaczego nie skorzystać z C++/CLI?

3

Cóż C++/CLI jest najczęściej przeznaczony do klejenia kodu zarządzanego i niezarządzanego. W związku z tym trzeba mieć możliwość wymieszania zmanipulowanych niezarządzanych koncepcji. Musisz mieć możliwość przydzielania zarządzanych i niezmienionych obiektów w tym samym kodzie, więc nie ma mowy o oddzielnych słowach kluczowych.

2

Po pierwsze, rozróżnienie między "prostym C++" i "zarządzanym C++" było zamierzone, ponieważ jednym z celów MC++ było zapewnienie mostu między istniejącym kodem C++ i CLR.

Następnie jest zbyt wiele funkcji C++, które nie pasują do modelu CLR. Wielokrotne dziedziczenie, szablony, arytmetyka wskaźników ... Bez rysowania czystej linii programiści byliby skazani na zmierzenie się z tajemniczymi błędami, zarówno podczas kompilacji, jak i w czasie wykonywania.

3

Dlaczego nie można skompilować natywnego kodu C++ kierującego do CLR?

Tak, zgadłeś, że byłoby zbyt wiele kompromisów, które uczyniłyby to bezużytecznym. Chciałbym wymienić tylko trzy przykłady ...

1.) Szablony: C++ je obsługuje, CLR nie (ogólne są różne). Więc nie możesz używać STL, boost itp. W swoim kodzie.

2.) Dziedziczenie wielokrotne: obsługiwane w C++, nie w CLI. Nie można nawet używać standardowej klasy iostream i pochodnych (takich jak stringstream, fstream), które dziedziczą zarówno z istream, jak i ostream.

Prawie żaden z kodu tam się nie skompilował, nie można nawet zaimplementować standardowej biblioteki.

3.) Usuwanie śmieci: Większość aplikacji C++ zarządza pamięcią ręcznie (przy użyciu inteligentnych wskaźników itp.), CLR ma automatyczne zarządzanie pamięcią. Zatem styl C++ "nowy" i "usuń" byłby niekompatybilny z "gcnew", czyniąc istniejący kod C++ bezużytecznym dla tego nowego kompilatora.

Jeśli musisz wykorzenić wszystkie ważne funkcje, nawet standardową bibliotekę, i żaden istniejący kod nie będzie się kompilował ... to o co ci chodzi?

+2

Szablony są wyłącznie konstruktorem czasu kompilacji. W przeciwieństwie do generycznych, nie potrzebują żadnej obsługi w czasie wykonywania. – Ferruccio

0

Tak, przypuszczam, że C++ może zostać zarządzony. Ale wtedy .NET musiałby być przepisany dla C++, a nie z uprzedzeniem w kierunku BASIC. Mając wiele języków pod jednym dachem. Niektóre funkcje muszą już iść. Był to wybór między VB.NET lub C++ .NET i wybrano VB.NET. Zabawne jest to, że C# jest bardziej popularny niż VB.NET (chociaż ja też nie używam!).

0

.NET CLR wymaga, aby żadne odniesienie do zarządzanego obiektu nigdy nie istniało w miejscu, o którym nie ma informacji o czasie pracy, z wyjątkiem sytuacji, gdy obiekt jest przypięty; Dobra wydajność wymaga, aby obiekty były przypięte jak najmniej. Od.NET CLR nie może zrozumieć wszystkich struktur danych, które są możliwe do użycia w C++, konieczne jest, aby w takich strukturach nie było nigdy żadnych odniesień do zarządzanych obiektów. Byłoby możliwe, aby "zwykły" kod C++ wchodził w interakcję z kodem .NET bez żadnych zmian w języku C++, ale jedynym sposobem, w jaki kod C++ mógłby zachować jakiekolwiek "odniesienie" do dowolnych obiektów .NET byłoby posiadanie jakiegoś kod po stronie .NET przypisuje każdemu obiektowi pewien uchwyt i zachowuje statyczną tabelę obiektów powiązanych z uchwytami. Kod C++, który chciał manipulować obiektami, musiałby wówczas poprosić o wrapper .NET, aby wykonać operację na obiekcie zidentyfikowanym przez uchwyt. Dodanie nowej składni umożliwia kompilatorowi identyfikację typów obiektów, o których powinna wiedzieć platforma .NET i wymuszenie na nich niezbędnych ograniczeń.

-1

Pierwszą rzeczą, którą należy wziąć pod uwagę, jest każda rzecz, która sprawia, że ​​c++ "szybko" zniknie. pełny system zbierania śmieci w języku C++ jest prawie niemożliwy. ponieważ c++ możesz mieć wskaźnik prawie w dowolnym miejscu w kodzie. Informacje o typie środowiska wykonawczego stają się kosztowne, jeśli nie są wbudowane bezpośrednio w system langauge . możesz skorzystać z prawdziwej wydajności natywnej. szablon zniknie. prawdziwe wskaźniki znikną. bezpośredni dostęp do pamięci zniknął.

lista rzeczy, które musiałyby być egzekwowane

1. no direct pointers(pointers will get replace with complex refernces) 
2. templates (generics pay for preformance) 
3. simple c-style arrays (will get wrapped with array structures) 
4. programmer no longer has control of whether data is on the stack or 
the heap. 
5. garbage collection will be enforced(this will cause the most changes to the syntax) 
6. runtime type data will get added extensively to the code. 
(larger code size) 
7. inlining will become more difficult for the compiler 
(no more inline key word) 
8. no more inline assembly. 
9. the new langauge by now will become incompatible c code.(unless you go through hoops) 
-1

zgadzam się z 5hammer! Jeśli opuściłem Javę i inne zarządzane języki, które nie są bezużyteczne: to ma mieć PEŁNĄ kontrolę nad komputerem, mieć dostęp do pamięci zarządzać pamięcią, mieć kontrolę nad tym, jak mój komputer będzie działał, integrować się z bibliotekami C (takimi jak Lua). Jeśli utracę tę elastyczność, po prostu zostawię C++ i powrócę do C, a jeśli C również zostanie zagospodarowany, to pójdę do asemblera.

Zarządzane języki są najgorszymi wersjami na wszystkich platformach do gier/złożonych programach, ponieważ ograniczają użytkownika w niektórych obszarach piaskownicy bez bezpośredniego dostępu do sprzętu i są znacznie wolniejsze niż języki kompilowane.

Głównym celem C++ zawsze była Performence. Jest to jeden z najlepszych języków dla dużych gier. Bez tego języka nie byłoby wielu gier!

Powiązane problemy