🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: pl.comp.lang.c
486 messages
486 total messages Page 1 of 10 Started by Hoobert Sat, 03 Nov 2007 09:47
Page 1 of 10 • 486 total messages
Ciemna strona C++
#267645
Author: Hoobert
Date: Sat, 03 Nov 2007 09:47
4 lines
977 bytes
Natkąłem się na takie coś: www.fefe.de/c++/c++-talk.pdf
W sumie nic nowego, ale kilka rzeczy dość fajnie pokazanych jest.
Jak dla mnie przykład z foo->bar w części "C++ is hard to read" jest 
dość wymowny.
Re: Ciemna strona C++
#267646
Author: SirMike
Date: Sat, 03 Nov 2007 10:26
16 lines
1645 bytes
Hoobert wrote:
> Natkąłem się na takie coś: www.fefe.de/c++/c++-talk.pdf
> W sumie nic nowego, ale kilka rzeczy dość fajnie pokazanych jest.
> Jak dla mnie przykład z foo->bar w części "C++ is hard to read" jest
> dość wymowny.

Jak dla mnie to autor, za przeproszeniem, pierdoli glupoty.
Zgadzam sie z czescia przedstawionych ulomnosci (np. ta o komunikatach
bledow kompilatora :D) ale duza czesc "featuresow" jest spotykana takze
w innych jezykach (Java, C#). Ogolnie tekst bardzo czepialski i subiektywny.

-- 
SirMike - http://www.sirmike.org
C makes it easy to shoot yourself in the foot;
C++ makes it harder, but when you do, it blows away your whole leg. -
Bjarne Stroustrup
Re: Ciemna strona C++
#267647
Author: Hoobert
Date: Sat, 03 Nov 2007 10:45
25 lines
2088 bytes
SirMike pisze:
> Hoobert wrote:
>> Natkąłem się na takie coś: www.fefe.de/c++/c++-talk.pdf
>> W sumie nic nowego, ale kilka rzeczy dość fajnie pokazanych jest.
>> Jak dla mnie przykład z foo->bar w części "C++ is hard to read" jest
>> dość wymowny.
> 
> Jak dla mnie to autor, za przeproszeniem, pierdoli glupoty.
> Zgadzam sie z czescia przedstawionych ulomnosci (np. ta o komunikatach
> bledow kompilatora :D) ale duza czesc "featuresow" jest spotykana takze
> w innych jezykach (Java, C#). Ogolnie tekst bardzo czepialski i subiektywny.
> 

Heh - no właśnie. Chociaż z drugiej strony nie jest napisane, że C++ 
jest blee bo to i to. Wiem, że obiektywniej by było jakby to nazywało 
się "Dark side of programming languages" i byłby przekrój przez kilka 
języków. Dla mnie to nie jest czepialstwo tylko pokazanie tego co jest.
Reszta zależy od interpretacji czytającego. Skoro autor nie pisze 
zarazem, ze w innych językach jest super to dla mnie to nie jest 
czepialstwo. IMHO złe ficzery są złymi niezależnie czy "konkurencja" je 
ma czy nie.

PS. Co do kuminaktów o błędach to http://www.bdsoft.com/tools/stlfilt.html

Pozdrawiam
Re: Ciemna strona C++
#267649
Author: Piotr Wyderski
Date: Sat, 03 Nov 2007 13:16
30 lines
2499 bytes
Hoobert wrote:

> Natkąłem się na takie coś: www.fefe.de/c++/c++-talk.pdf

Mam mieszane uczucia. Legendarna czytelność komunikatów
o błędach jest poza dyskusją, ale z drugiej strony człowiek
przyczepia się do złożoności obliczeniowej typowania -- to
jest bez sensu, bo język szablonów może prowadzić do
bardzo drogich obliczeń i wynika to z ich struktury, a nie
z tego, że to C++. Nie zgadzam się też z zarzutami w sprawie
<iostream.h> i że doszły przestrzenie nazw: po prostu nieco
posprzątano wcześniejszy bałagan. Zgadzam się za to w pełni
w sprawie operatorów ||, && i kolejności obliczania wyrażeń.
Rozmawialiśmy o tym ostatnio i pisałem, że dzis dawanie
kompilatorowi wolnej ręki w sprawie kolejności obliczania
wyrażeń nie prowadzi do żadnego wzrostu wydajności.

Do tego dokładam zbyt liberalne niejawne konwersje z typów
całkowitych na bool oraz wskaźniki. Używanie 0 w charakterze
null jest całkowicie bez sensu, bo znacznie utrudnia pisanie
lub używanie szablonów funkcji operujacych na wskaźnikach.
Trzeba pisać albo static_cast<> w wywołaniu, albo dodać
warianty dla int, które muszą sprawdzać, czy dowcipny
użytkownik nie podał czegoś innego niż szcególny przypadek 0.
Gdyby null miał własny typ, te sprawy byłyby znacznie
czytelniejsze. Właśnie z tego powodu napisałem sobie lata
temu klasę null_ptr i jej instancję null.

    Pozdrawiam
    Piotr Wyderski
Re: Ciemna strona C++
#267650
Author: Seweryn Habdank-Wojewódzki
Date: Mon, 05 Nov 2007 22:23
25 lines
1762 bytes
Witam

Piotr Wyderski wrote:

> to
> jest bez sensu, bo język szablonów może prowadzić do
> bardzo drogich obliczeń i wynika to z ich struktury

Czy możesz dać przykład?

Mam kompletnie inne doświadczenia. Kod obliczeniowy powstały jako policy
classes dla szablonów algorytmów jest u mnie szybszy niż kod oparty o
wzorzec template method, czy inne pochodne po wskaźnikach do funckji. A to
dlatego, że funktory są agresywnie i to bardzo agresywnie inlineowane i
optymalizowane część obliczeń jest również dokonywana w czasie kompilacji.
Do tego dorzucam parametryzowanie rozmiarem przydzielanych tablic z danymi
to daje kolejny bonus. Mam np. pulę funktorów filtrujących w oknach, pula
funktorów zawiera różne rozmiary okien wkompilowane. Algorytm wybiera jeden
z nich (rozmiar okna) nie mam dynamicznie przydzielanej pamięci.

Pozdrawiam.

-- 
|\/\/|   Seweryn Habdank-Wojewódzki
 \/\/
Re: Ciemna strona C++
#267651
Author: Tomasz bla Fortuna
Date: Tue, 06 Nov 2007 06:30
25 lines
1742 bytes
Dnia Mon, 05 Nov 2007 23:23:33 +0100
Seweryn Habdank-Wojewódzki <shw_mail@wp.pl> napisał(a):
> Piotr Wyderski wrote:
> > to
> > jest bez sensu, bo język szablonów może prowadzić do
> > bardzo drogich obliczeń i wynika to z ich struktury
> 
> Czy możesz dać przykład?
> 
> Mam kompletnie inne doświadczenia. Kod obliczeniowy powstały jako
> policy classes dla szablonów algorytmów jest u mnie szybszy niż kod
> oparty o wzorzec template method, czy inne pochodne po wskaźnikach do
> funckji. A to dlatego, że funktory są agresywnie i to bardzo
> agresywnie inlineowane i optymalizowane część obliczeń jest również
> dokonywana w czasie kompilacji.

AFAIR chodziło właśnie o koszt obliczeń potrzebny do skompilowania
szablonów, a nie run-time.

Pozdrawiam.
-- 
Tomasz bla Fortuna
jid: bla(at)af.gliwice.pl
pgp: 0x90746E79 @ pgp.mit.edu
www: http://bla.thera.be
Re: Ciemna strona C++
#267652
Author: Seweryn Habdank-Wojewódzki
Date: Tue, 06 Nov 2007 21:58
18 lines
1349 bytes
Witam

Tomasz bla Fortuna wrote:

> AFAIR chodziło właśnie o koszt obliczeń potrzebny do skompilowania
> szablonów, a nie run-time.

A to przepraszam. A co to szkodzi, że kompilacja trwa dłużej? Czy ta
kompilacja odpalana jest w run-time?

Odniosłem się *tylko* do postu Piotra. Ostatnio nie mam czasu czytać
wszystkich wypocin szanownego gremium ktytykantów C i C++ :-).

Pozdrawiam.

-- 
|\/\/|   Seweryn Habdank-Wojewódzki
 \/\/
Re: Ciemna strona C++
#267653
Author: Paweł Kierski
Date: Wed, 07 Nov 2007 10:30
18 lines
1782 bytes
Seweryn Habdank-Wojewódzki w wiadomości <fgqn9m$74j$2@news.vectranet.pl> pisze:
[...]
> Odniosłem się *tylko* do postu Piotra. Ostatnio nie mam czasu czytać
> wszystkich wypocin szanownego gremium ktytykantów C i C++ :-).

  A to źle! 8-) Ktoś może mieć rację i warto o tym wiedzieć.

  Pomijąc fakt, że to, co napisałeś, niebezpiecznie zbliża się do
kwestii Kaowca: "Nie słyszałem piosenki, więc chciałem powiedzieć parę
słów na jej temat".

  Tak wytykam, a i mnie się zdarza 8-)

-- 
    Paweł Kierski
    news@pkierski.net
    dodaj "[nomorespam]" w temacie jeśli piszesz z domeny innej niż .pl,
    albo koniecznie chcesz obejść moje filtry 8-)
Re: Ciemna strona C++
#267654
Author: Seweryn Habdank-Wojewódzki
Date: Wed, 07 Nov 2007 20:37
62 lines
3271 bytes
Witam

Paweł Kierski wrote:

>> Odniosłem się *tylko* do postu Piotra. Ostatnio nie mam czasu czytać
>> wszystkich wypocin szanownego gremium ktytykantów C i C++ :-).
> 
>   A to źle! 8-) Ktoś może mieć rację i warto o tym wiedzieć.

Masz rację, przyznałem się i w ramach pokuty, obejrzałem ten pdf.

NIC, kompletnie NIC nowego. Przedstawione problemy są dla mnie żenujące.

Slajdy 2-5 komunikaty o błędach. Przedstawił komunikaty z kompilatora gcc
wszyscy wiedzą, że gcc produkuje najobszerniejsze komunikaty. Szkoda, że
nie pokazał tego komunikatu w innym kompilatorze.

Slajd 6 ostatnie linijka tekst w () jest chyba wynikiem tego, że ktoś
pokazując komunikaty z gcc, nie używa g++ tylko gcc.

7 -- chłopina narzeka, że standard wniósł zmiany w C++ po roku 1997.
Powinien zobaczyć ile zmian zaszło pomiędzy 1995 a rokiem powstania slajdów
w innych językach.

8 -- to jest jakaś kompletna głupota, aby komuś przeszkadzała taka
możliwość.

9 -- 2 i 3 zdanie są jakimiś kłopotami kolesia z kodowaniem w ogóle.

11 -- pozostawię bez komentarza, bo Pan Felix poprosił się o kłopoty, a
kompilator wykonuje o co go poproszono. Skąd niby kompilator ma wiedzieć
sam od siebie, że ktoś ma lub nie podstawy do tworzenia tak bardzo
zagnieżdżającego się szablonu? Pomijam fakt, że to jest problem
kompilatora, a nie języka. Ciekawy jestem, czy Panu Falixowi wpadł do głowy
pomysł, że pętla typu int i = 0; while(1) { x = new Type[i]; ++i } w
dowolnym języku tak samo pośle do piachu program, tudzież jej wersja
rekurencyjna.


12 -- to samo co 11, kolo prosi się o guza więc obrywa w głowę i płacze, ten
facio ma chyba jakąś odmianę masochizmu, wbija sobie gwoździe w udo, a
potem płacze, że boli, ale nie kapuję czemu mu to sprawia satysfakcję.

13 -- żal mi kogoś kto ma zakute w głowie, że gramatyka języka ma być
sprowadzona do poziomu Logo.



W każdym języku takie będzie kłopotem.


 
>   Pomijąc fakt, że to, co napisałeś, niebezpiecznie zbliża się do
> kwestii Kaowca: "Nie słyszałem piosenki, więc chciałem powiedzieć parę
> słów na jej temat".
> 
>   Tak wytykam, a i mnie się zdarza 8-)
> 

-- 
|\/\/|   Seweryn Habdank-Wojewódzki
 \/\/
Re: Ciemna strona C++
#267648
Author: Mateusz Loskot
Date: Wed, 07 Nov 2007 20:45
10 lines
1062 bytes
Hoobert wrote:
> 
> PS. Co do kuminaktów o błędach to http://www.bdsoft.com/tools/stlfilt.html

Albo Visual C++ 2005 :-)

Pozdrawiam
-- 
Mateusz Loskot
http://mateusz.loskot.net
Re: Ciemna strona C++
#267655
Author: Seweryn Habdank-Wojewódzki
Date: Wed, 07 Nov 2007 21:50
139 lines
7296 bytes
Witam

Seweryn Habdank-Wojewódzki wrote:

> 11 -- pozostawię bez komentarza, bo Pan Felix poprosił się o kłopoty, a
> kompilator wykonuje o co go poproszono. Skąd niby kompilator ma wiedzieć
> sam od siebie, że ktoś ma lub nie podstawy do tworzenia tak bardzo
> zagnieżdżającego się szablonu? Pomijam fakt, że to jest problem
> kompilatora, a nie języka. Ciekawy jestem, czy Panu Felixowi wpadł do
> głowy pomysł, że pętla typu int i = 0; while(1) { x = new Type[i]; ++i } w
> dowolnym języku tak samo pośle do piachu program, tudzież jej wersja
> rekurencyjna.


void foo (int & i)
{
        ++i;
        x = new Type[i];
        foo (i);
}

W każdym języku takie będzie kłopotem.
 
13 -- jakiś obłęd, co on chce pokazać?

14 -- pierwszy faktycznie jest problematyczny. Drugi, już był o tym flame.
auto_ptr, już nie raz potrzebowałem tego wskaźnika w takiej wersji jakiej on
jest, czyli aby "szkodliwe" przenoszenie referencji zadziałało tak jak
działa w auto_ptr. Jak mu auto_ptr szkodzi, niech go nie używa.
Co on chce od iteratora, w innym wątku kiedyś pokazałem jak wzbogacić
iterator, aby wiedział o obiekcie, ale Pan Felix w swojej "sprawności"
kodowania przykładzików nie wpadł na pomysł jak dociążyć iterator.
Uwaga o at i [] jest nie uzupełniona o informację o wydajności at i [].
Informacja o nie możności wołania z konstruktora wirtualnych metod jest dla
mnie dziwna, bo nie widzę projektowych podstaw aby wykonywać taką sztuczkę,
ale może Pan Felix jest arcy designerem i miał coś konkretnego na myśli.

16 -- wymieszał konstruktory i destruktory oraz ich kłopoty w jednym
tygielku, ten slajd jest do poprawy, bo tylko miesza.

17 -- był już flame.

18 -- jak dla mnie to jest specyfikacja auto_ptr, a nie wykazywanie wad. Jak
mu nie pasuje niech używa shared, scoped, czy innych. Podkreślę jeszcze raz
te "wady" w jednym projekcie u mnie są zaletami, bo stosowne wskaźniki są
właśnie przenoszone i jedne nadobiekty oddaja własność drugim nadobiektom,
do swoich podobiektów.

19 -- o czym on mówi? Czy on może chce, aby iterator był dołączony do
obiektu, a może jak obiekt ma 5 MB, to też ma wszystko wiedzieć o
pojedynczym obiekcie? A jak tych obiektów w kolekcji jest dzikie mnóstwo
to, co? Ile informacji potrzebuje mieć iterator, aby wszyscy przestali się
czepiać, że on czegoś nie wie. Jeden powie, że chce wiedzieć czy obiekt się
zmienił, inny, że jest inny typ polimorficzny jeszcze ktoś zarząda, aby
iterator znał rozmiar kontenera, a ostatni zażąda, aby iterator za niego
myślał i pisał programy. Zresztą banalne jest związanie iteratora i
kontenera wrapując oba w jednym obiekcie.

20 -- o co Panu Felixowi chodzi. Po co funkcja at(), jeśli operator[]
robiłby to samo?

21 -- może powinien jeszcze napisać, że w konstruktorze nie może
użyć "this", to byłby komplet życzeń.

22 -- dorzucam, że można zrobić takie coś: 
gdzieś w odległym headerze globalnie stworzony zestaw define:

#define private public
#define protected public
#define const 
#define volatile
#define class struct

oh, oh, ale podniecenie, ileż to można zrobić złych rzeczy.

23 - 31 -- jak napiszę w innym języku:

baz = foo.bar(3) to też nic nie wiem. Do tego są możliwości, że kod jest tak
napisany, że ta "3" staje się jakąś wartością globalną, czy mam za to
besztać te inne języki?

SPECYFIKACJA i OPIS KLAS jest od tego aby wyjaśnić dokładnie co się dzieje.

32 i 33 -- zapomniał Pan Felix o const, czy to go boli? Czy jeśli żąda
czegoś innego od referencji niż od wartości, to może operować constem.
A może ma jeszcze coś innego na myśli?

34 i 35 -- Super. Język ma być łatwy! Też tak, chce, aby Haskel i Lisp były
łatwe, aby asembler był łatwy. Jakoś jest tak, że język, który oferuje
więcej niż Logo, musi być nieco trudniejszy. Ten Pan ma jakieś kłopoty
chyba z uczeniem się w ogóle, bo takie zarzuty można kierować do każdej
nauki zaczynając od jej wysokości królowej nauk (matematyka) ona to daje
popalić. W szkole dodajemy, mnożymy, dzielenie w słupku jest trudne (?).
Potem coś dalej jakieś gimnazjum , każą potęgować i liczyć pola figur --
toż to przecież jest zamach na łatwość życia, powinny takie rzeczy być już
policzony, a my powinniśmy wysłuchać , że ktoś to policzył. I tak aż do
końca studiów słuchłamy, że ktoś coś zrobił, ale sami trudu nie wkładamy w
naukę. Potem pensyjkę żądamy 6 cyferek (w skali roku). Ale świat jest
brutalny mało znam ludzi którzy całe życie mają podane na tacy. raczej znam
takich co pokonując trud nauki i pracy osiągają stosowne pensje. Wracając
do języków. Proste języki np. Logo, HTML są albo dedykowane i nadają się
świetnie do wąskich zadań, a trudne języki są do zadań szerzej określonych.

36 -- zgada się, tylko co to wnosi?

37 -- 1: bzdura; 2: nie wiem o co chodzi (na czym polega rzeczywisty
kłopot); 3: a specyfikacje funkcji to Pan Felix czytuje?

38 -- mówił, że lubi C, a tam są te same problemy i na dodatek łata się je o
wiele gorzej niż w C++.

39 -- o jaki ten Pan mądry, wpakował kod języka C, do funkcji C++ beż
żadnego opakowania i płacze. To są łatwe do wychwycenia błędy. Znam gorsze
w środowisku wielo wątkowym, które są kłopotliwe nie zależnie od języka.

40 -- no tak, a kto tak projektuje kod nawet w języku C. Co to za zwyczaj,
aby obiekt kasował nie ten co go przydziela?

... męczące jest zastanawianie się ile można brzydkich przykładów podać w
dowolnym języku programowania ... bo w każdym to jest możliwe.

47 -- chłopina rzutuje obiekt foo na bar a potem dziwi się, że "mu to nie
działa". Mi to w ogóle ten kod nie działa, a jak go poprawiłem to mi działa
dobrze.

>>   Pomijąc fakt, że to, co napisałeś, niebezpiecznie zbliża się do
>> kwestii Kaowca: "Nie słyszałem piosenki, więc chciałem powiedzieć parę
>> słów na jej temat".
>> 
>>   Tak wytykam, a i mnie się zdarza 8-)

Masz rację, że wytykasz :-).

Pozdrawiam.
 

-- 
|\/\/|   Seweryn Habdank-Wojewódzki
 \/\/
Re: Ciemna strona C++
#267656
Author: Maciej Piechotka
Date: Wed, 07 Nov 2007 22:22
31 lines
1930 bytes
On Wed, 07 Nov 2007 22:50:47 +0100, Seweryn Habdank-Wojewódzki wrote:

> void foo (int & i)
> {
>         ++i;
>         x = new Type[i];
>         foo (i);
> }
> 
> W każdym języku takie będzie kłopotem.

W zasadzie język z GC będzie(a przynajmniej powinien) płakał wył i 
wyczyniał inne rzeczy z wydajnością ale będzie miał tylko przepełniony 
stos (jaśli nie zostanie zoptymalizowane do pętli).

void foo(int &i, int *x)
{
  int *y = new int[i + 1];
  std::copy(x, &x[i], y);
  y[i] = i;
  foo(++i, y);
  delete y;
}

Zoptymalizuje się dużo gorzej ;) w każdym języku.

Pozdrawiam
-- 
I've probably left my head... somewhere. Please wait untill I find it.
Homepage (pl_PL): http://uzytkownik.jogger.pl/
(GNU/)Linux User: #425935 (see http://counter.li.org/)
Re: Ciemna strona C++
#267657
Author: Sebastian Kaliszewski
Date: Thu, 08 Nov 2007 14:41
91 lines
4269 bytes
Seweryn Habdank-Wojewódzki wrote:
> 13 -- jakiś obłęd, co on chce pokazać?

Że język jest zrobiony od d. strony?


> 19 -- o czym on mówi? Czy on może chce, aby iterator był dołączony do
> obiektu, a może jak obiekt ma 5 MB, to też ma wszystko wiedzieć o
> pojedynczym obiekcie? 

Po co? Wzkaźniki już nie istnieją?

> A jak tych obiektów w kolekcji jest dzikie mnóstwo
> to, co? Ile informacji potrzebuje mieć iterator, aby wszyscy przestali się
> czepiać, że on czegoś nie wie.

Powinien wiedzieć po czym iteruje. Tak, żeby nie było UBecji.

[...]
 > Zresztą banalne jest związanie iteratora i
> kontenera wrapując oba w jednym obiekcie.

Typowe gadanie z C++ -- zrób se sam. W C++ wszystko jest zrób se sam, bo 
biblioteka standardowa jest biedna i prymitywna.


> 32 i 33 -- zapomniał Pan Felix o const, czy to go boli? Czy jeśli żąda
> czegoś innego od referencji niż od wartości, to może operować constem.
> A może ma jeszcze coś innego na myśli?

To, że w wywołaniu nie wiesz czy parametr będzie modyfikowany czy nie.


> 34 i 35 -- Super. Język ma być łatwy! Też tak, chce, aby Haskel i Lisp były
> łatwe, aby asembler był łatwy. Jakoś jest tak, że język, który oferuje
> więcej niż Logo, musi być nieco trudniejszy.

Taaak, bo takie potworki jak boost::mpl czy boost::spirit to są niezwykle 
potrzebne


> 36 -- zgada się, tylko co to wnosi?

W koślawym języku traci się kupę czasu na przeskakiwanie koślawości?


> 37 -- [...] 2: nie wiem o co chodzi (na czym polega rzeczywisty
> kłopot);

Code bloat.

> 38 -- mówił, że lubi C, a tam są te same problemy i na dodatek łata się je o
> wiele gorzej niż w C++.

W C są wyjątki??? iteratory??? desytuktory????


> 39 -- o jaki ten Pan mądry, wpakował kod języka C, do funkcji C++ beż
> żadnego opakowania i płacze. To są łatwe do wychwycenia błędy. Znam gorsze
> w środowisku wielo wątkowym, które są kłopotliwe nie zależnie od języka.
> 
> 40 -- no tak, a kto tak projektuje kod nawet w języku C. Co to za zwyczaj,
> aby obiekt kasował nie ten co go przydziela?

To jest normalny zwyczaj. Tylko w nienormalnych językach to sprawia problem :)

> ... męczące jest zastanawianie się ile można brzydkich przykładów podać w
> dowolnym języku programowania ... bo w każdym to jest możliwe.

Ale w innych językach tego problemu po prostu nie ma.


> 47 -- chłopina rzutuje obiekt foo na bar a potem dziwi się, że "mu to nie
> działa".

Co rzutuje? Przecież to jest "normalny" polimorfizm.

Pokazana jedna z projektowych przypadłości C++ -- niekontrolowane nakłądanie 
się na siebie cech, na skutek niedostatecznego przemyślenia skutków 
dodawania określoncyh ficzerów -- połączenie odziedziczonego z C pomieszania 
wskaźników z tablicami z obiektowym polimorfizmem rodzi kaszanę.

Inny przykład to słynne >> w szablonach.

> Mi to w ogóle ten kod nie działa, a jak go poprawiłem to mi działa
> dobrze.

Taaaak??!?!?!? O, to ciekawe!

pzdr
\SK
Re: Ciemna strona C++
#267658
Author: Seweryn Habdank-Wojewódzki
Date: Thu, 08 Nov 2007 18:45
180 lines
8383 bytes
Witam

Sebastian Kaliszewski wrote:

>> 19 -- o czym on mówi? Czy on może chce, aby iterator był dołączony do
>> obiektu, a może jak obiekt ma 5 MB, to też ma wszystko wiedzieć o
>> pojedynczym obiekcie?
> 
> Po co? Wzkaźniki już nie istnieją?

Wskaźnik przecież może pokazywać na NULL? Przecież wskaźnik nie wie czy
obiekt się zmienił (wzorzec obserwator się kłania).
Pan F. nie pokazuje jak coś nie działa i jest to zrobione w dobrym stylu
C++. Wymaścił jakieś kodziki i płacze, że mu nie działa. W tym stylu
potrafię rozwalić każdy kod w C, J, i Py. # nie umiem na tyle, aby to
zrobić, ale na pewno na tej grupie są geekowie, co potrafią grzebać we
wnętrznościach #.

>> A jak tych obiektów w kolekcji jest dzikie mnóstwo
>> to, co? Ile informacji potrzebuje mieć iterator, aby wszyscy przestali
>> się czepiać, że on czegoś nie wie.
> 
> Powinien wiedzieć po czym iteruje. Tak, żeby nie było UBecji.

O tak. Każdy iterator powinien być wizytatorem, obserwatorem, kompozytem,
mózgiem i wiedzą kodera w jednym.

Iterator przede wszystkim ma być efektywną abstrakcją, a nie kombajnem.
 
>> Zresztą banalne jest związanie iteratora i
>> kontenera wrapując oba w jednym obiekcie.
> 
> Typowe gadanie z C++ -- zrób se sam. W C++ wszystko jest zrób se sam, bo
> biblioteka standardowa jest biedna i prymitywna.

Tak. A i tak kolesie pokroju Pana F. nie używają jej -- przykład tablica
obiektów typu foo rzutowana na bar*. Użycie STL na poziomie 0.

Poza tym już nie traz narzekałeś na STL więc skąd nagle gadanie o tym,
że "zrób se sam" jest złe? Pan F. jak widać STL'a nie używa tak jak to
należy robić -- jedyne co potrafi to napisać baziewny kod, aby wykazać, że
gcc generuje długie błędy.
 
>> 32 i 33 -- zapomniał Pan Felix o const, czy to go boli? Czy jeśli żąda
>> czegoś innego od referencji niż od wartości, to może operować constem.
>> A może ma jeszcze coś innego na myśli?
> 
> To, że w wywołaniu nie wiesz czy parametr będzie modyfikowany czy nie.

Do tego właśnie służy CONST!!!
 
>> 34 i 35 -- Super. Język ma być łatwy! Też tak, chce, aby Haskel i Lisp
>> były łatwe, aby asembler był łatwy. Jakoś jest tak, że język, który
>> oferuje więcej niż Logo, musi być nieco trudniejszy.
> 
> Taaak, bo takie potworki jak boost::mpl czy boost::spirit to są niezwykle
> potrzebne

Oh. Przeszkadza Ci, że ktoś myśli bardziej abstrakcyjnie niż łepsajty tego
wymagają? Pokaż mi takie cos jak MPL i SPIRIT w J i w Py.

J wyciera sobie twarz XML i to równiutko, a jak chcesz mieć coś innego niż
XML, to ci mówią, że ... hmm ... ę ... tego ... yyy ... ten tego,
"poco ci coś innego niż XML?"

Parsery wszędzie pisze się parszywie. Więc Twój argument, że Spirit jest
potworny jest nietrafiony.

Co do MPL. Np. w konstrukcji rozmytego algorytmu predykcyjnego mam kawałki z
boost::mpl (dziś lepiej jest używać boost::fusion).

Jest to raczej poprawa czytelności, niż utrudnienie. Np. mam takie coś:

mpl::vector < TrapMf, TriMf, TriMf, TriMf, TrapMf >

a w bardziej dynamicznym kontekście:

mpl::vector < shared_ptr<MembershipFunction>, ...
shared_ptr<MembershipFunction>, >

Co można jeszcze bardziej zdynamizować:

std::vector < shared_ptr<MembershipFunction> >

Kłopot polega na tym, w którym miejscu żądam jakich gwarancji. Każda z tych
wersji jest w różnych miejscach kodu. W szczególności mam takie miejsca
gdzie pierwszy kod jest jedynym słusznym rozwiązaniem (zamienić MPL można
na boost::tuple), ale kod jest podobny.

To oczywiście nie jest łepsajt i daleko temu do tego. 
Ale to też nie jest "wydumana sprawa" bo takie konstrukcje stanowią podstawę
Data Miningu. Dla którego powoli oficjalnie jest wsparcie zarówno bazach
danych (Oracle) jak i w językach -- J2EE wyposażone jest w pewien ubogi
projekt do Data Miningu.

>> 36 -- zgada się, tylko co to wnosi?
> 
> W koślawym języku traci się kupę czasu na przeskakiwanie koślawości?

Ha, ha, ha. Tylko, że Pan F. pisze, że lubi C, a tam aż roi się o void* (*)
(void*). I to boli nie na żarty.
 
>> 38 -- mówił, że lubi C, a tam są te same problemy i na dodatek łata się
>> je o wiele gorzej niż w C++.
> 
> W C są wyjątki??? iteratory??? desytuktory????

Nie ma. Są za to inne kwiatki. A w innych językach? Wystarczy sprawnie jak w
dobrej szkole Troli zapodać na grupę post typu. "Słyszałem, że w języku XXX
nie da się zrobić czegoś takiego jak YYY". Ach zaraz masz 1001 przepisów
jak w dowolnym języku XXX można zrobić paskudniaczka. Do tego jeszcze
chłopaki prześcigać się będą jak to wykonać najbardziej ekstremalnie -- bo
przecież się da. Wszędzie się da kod spaskudzić.
 
>> 40 -- no tak, a kto tak projektuje kod nawet w języku C. Co to za
>> zwyczaj, aby obiekt kasował nie ten co go przydziela?
> 
> To jest normalny zwyczaj. Tylko w nienormalnych językach to sprawia
> problem :)

Tak? A gdzie to jest normalny zwyczaj? Jeśli gdzieś są takie zwyczaje to
kończy się to na posiadaniu GC. A ciekawie się dzieje, kiedy sam zaczniesz
grzebać w tym co robi GC i np. rozgrzebiesz w GC to na czym pracuje GC.
 
>> ... męczące jest zastanawianie się ile można brzydkich przykładów podać w
>> dowolnym języku programowania ... bo w każdym to jest możliwe.
> 
> Ale w innych językach tego problemu po prostu nie ma.

Nie prawda. Zobacz sobie na to:

http://qsorix.jogger.pl/2006/12/14/java-jezyk-pelen-niespodzianek

To jest właśnie poziom haków Pana F.

Zrobić coś nie całkiem tak, jak to się powinno robić, a potem gadać o
wadach.

Dorzucam do tego jeszcze mój stary problem jak wyleczyć wadę projektową
generyków J, która nazwana jest ficzerem "erasure". 
Wiesz jaki potworek trzeba napisać, aby twój generyk pomimo wszystko
nie "erasurował się"? Oczywiście (na szczęście) da się to wyleczyć.

>> 47 -- chłopina rzutuje obiekt foo na bar a potem dziwi się, że "mu to nie
>> działa".
> 
> Co rzutuje? Przecież to jest "normalny" polimorfizm.

Tak? Jeśli tak piszesz normalne programy. To nie dziwię się, że uciekasz od
C++.
 
> Pokazana jedna z projektowych przypadłości C++ -- niekontrolowane
> nakłądanie się na siebie cech, na skutek niedostatecznego przemyślenia
> skutków dodawania określoncyh ficzerów -- połączenie odziedziczonego z C
> pomieszania wskaźników z tablicami z obiektowym polimorfizmem rodzi
> kaszanę.

C++ zawrapował C bardziej dosłownie niż to robią inne języki, np. CPython.
Czy wadą CPythona jest to, że możesz też kod napisać w C?
 
> Inny przykład to słynne >> w szablonach.

A gdzie nie ma słynnych przykładów? W Pythonie jak dla mnie słynnym
przykładem jest kasowanie metod z klas. Wada czy zaleta?

I pytanie bonus jak skasujesz metodę z klasy, to jak ją odzyskać?
 
>> Mi to w ogóle ten kod nie działa, a jak go poprawiłem to mi działa
>> dobrze.
> 
> Taaaak??!?!?!? O, to ciekawe!

Po prostu wystarczy ten kod napisać sensownie, a nie udowadniając tego co
Pan F. chciał wykazać.

Pozdrawiam.

-- 
|\/\/|   Seweryn Habdank-Wojewódzki
 \/\/
Re: Ciemna strona C++
#267659
Author: Maciej Piechotka
Date: Thu, 08 Nov 2007 20:49
39 lines
2380 bytes
On Thu, 08 Nov 2007 19:45:33 +0100, Seweryn Habdank-Wojewódzki wrote:

>>> ... męczące jest zastanawianie się ile można brzydkich przykładów
>>> podać w dowolnym języku programowania ... bo w każdym to jest możliwe.
>> 
>> Ale w innych językach tego problemu po prostu nie ma.
> 
> Nie prawda. Zobacz sobie na to:
> 
> http://qsorix.jogger.pl/2006/12/14/java-jezyk-pelen-niespodzianek
> 
> To jest właśnie poziom haków Pana F.
> 
> Zrobić coś nie całkiem tak, jak to się powinno robić, a potem gadać o
> wadach.
> 
> Dorzucam do tego jeszcze mój stary problem jak wyleczyć wadę projektową
> generyków J, która nazwana jest ficzerem "erasure". Wiesz jaki potworek
> trzeba napisać, aby twój generyk pomimo wszystko nie "erasurował się"?
> Oczywiście (na szczęście) da się to wyleczyć.

Najpopularniejsze jest chyba:

class Test<T> {
  public Test(Class<T> t) {
    
  }
}

I:
Test<String> test = new Test<String>(String.class);

SPOT?

Pozdrawiam
-- 
I've probably left my head... somewhere. Please wait untill I find it.
Homepage (pl_PL): http://uzytkownik.jogger.pl/
(GNU/)Linux User: #425935 (see http://counter.li.org/)
Re: Ciemna strona C++
#267660
Author: Seweryn Habdank-Wojewódzki
Date: Thu, 08 Nov 2007 21:53
28 lines
1746 bytes
Witam

Maciej Piechotka wrote:

> Najpopularniejsze jest chyba:
> 
> class Test<T> {
>   public Test(Class<T> t) {
>     
>   }
> }
> 
> I:
> Test<String> test = new Test<String>(String.class);
> 
> SPOT?

Tak. To jest miłe rozwiązanie, chociaż ma przywarę, że wzrostem liczby typów
i konstruktorów jego składnia się komplikuje, ale nie mam ochoty dowodzić
wad, tak jak Pan F na podstawie tego, że są w języku J jakieś koszmarki.
Wolę czepiać się rzeczy w kodzie pisanym poprawnie i zgodnie z duchem
języka.

Pozdrawiam.

-- 
|\/\/|   Seweryn Habdank-Wojewódzki
 \/\/
Re: Ciemna strona C++
#267661
Author: Sebastian Kaliszewski
Date: Fri, 09 Nov 2007 15:31
342 lines
11670 bytes
Seweryn Habdank-Wojewódzki wrote:
>>>19 -- o czym on mówi? Czy on może chce, aby iterator był dołączony do
>>>obiektu, a może jak obiekt ma 5 MB, to też ma wszystko wiedzieć o
>>>pojedynczym obiekcie?
>>
>>Po co? Wzkaźniki już nie istnieją?
> 
> Wskaźnik przecież może pokazywać na NULL? Przecież wskaźnik nie wie czy
> obiekt się zmienił (wzorzec obserwator się kłania).

Jaki obserwator? Obserwator to jest bardzo złe rozwiązanie takiego 
przypadku. Obserwator służy do rozprowadzania zdarzeń (edge triggered) a nie 
udostępniania informacji o bieżącym stanie (level triggered).


To się robi tak:

template <typename T>
class container
{
   struct testament_t
   {
     typedef unsigned long state_t

     state_t state;

     testament_t(): state(1);
   }

   typedef std::tr1::shared_ptr<testament_T> testament_ptr;

   class iterator
   {
      testament_ptr creator_testament;
      testament_t::state_t initial_state;

      ...

      iterator(testament_ptr t, ...):
        creator_testament(t), initial_state(t->state), ...
      {...}

      T& operator* ()
      {
        if(creator_testament->state != initial_state)
	 throw invalid_iterator(); // albo abort() -- jak kto woli
        ...
      }

      ...
   };


   testament_ptr testament;

   void update_testament()
   {
     testament->state++;
     if(testament_state == 0)
     {
       testament = new testament_t();
     }
   }

   void last_testament()
   {
     testament->state = 0;
   }

   ...

public:
   container(...): testament(new testament_t()), ... {...}

   ~container()
   {
      last_testament();
      ...
   }

   void invalidating_modify(...)
   {
      update_testament();
      ...
   }

   iterator begin()
   {
     ...
     return iterator(testament, ...);
   }

};


Nie wiem jak się ten wzorzec nazwa, jeśli nie ma nazwy, to można go nazwać 
Testament :)  (infromacje dla przyjaciół (friends) i innych zstępnych 
zawierające wolę testamentodawcy, również po jego śmierci).


> Pan F. nie pokazuje jak coś nie działa i jest to zrobione w dobrym stylu
> C++. 

Użycie iteratorów jest w złym stylu C++ ???


>>>A jak tych obiektów w kolekcji jest dzikie mnóstwo
>>>to, co? Ile informacji potrzebuje mieć iterator, aby wszyscy przestali
>>>się czepiać, że on czegoś nie wie.
>>
>>Powinien wiedzieć po czym iteruje. Tak, żeby nie było UBecji.
> 
> O tak. Każdy iterator powinien być wizytatorem, obserwatorem, kompozytem,
> mózgiem i wiedzą kodera w jednym.

Patrz wyżej. To jest proste, tanie i szybkie.


> Iterator przede wszystkim ma być efektywną abstrakcją, a nie kombajnem.

A potem płacz, że jakiś gówniarz włamał się i wszystko pokasował. Albo, że 
odcieli od Internetu, bo komputer był shackowany i rozsyłał spam.


>>>Zresztą banalne jest związanie iteratora i
>>>kontenera wrapując oba w jednym obiekcie.
>>
>>Typowe gadanie z C++ -- zrób se sam. W C++ wszystko jest zrób se sam, bo
>>biblioteka standardowa jest biedna i prymitywna.
> 
> 
> Tak. A i tak kolesie pokroju Pana F. nie używają jej -- przykład tablica
> obiektów typu foo rzutowana na bar*.

To czemu język na to pozwala? Statyczny system typów? ROTFL! To jest 
Dziurawy System Typów(tm).


 > Użycie STL na poziomie 0.
> 
> Poza tym już nie traz narzekałeś na STL więc skąd nagle gadanie o tym,
> że "zrób se sam" jest złe? Pan F. jak widać STL'a nie używa tak jak to
> należy robić -- jedyne co potrafi to napisać baziewny kod, aby wykazać, że
> gcc generuje długie błędy.

Skąd wiesz czego on używa a czego nie?

Obraziłeś się, że najechał na twój kochany język, i o zgrozo, najazd jest celny.


>>>32 i 33 -- zapomniał Pan Felix o const, czy to go boli? Czy jeśli żąda
>>>czegoś innego od referencji niż od wartości, to może operować constem.
>>>A może ma jeszcze coś innego na myśli?
>>
>>To, że w wywołaniu nie wiesz czy parametr będzie modyfikowany czy nie.
> 
> Do tego właśnie służy CONST!!!

Co ty wyyślasz???!!?!?!?!?!?!?

int dupa(int niemodyfikowany, int& modyfikowany);

gdzie masz jakieś const??!?!


>>>34 i 35 -- Super. Język ma być łatwy! Też tak, chce, aby Haskel i Lisp
>>>były łatwe, aby asembler był łatwy. Jakoś jest tak, że język, który
>>>oferuje więcej niż Logo, musi być nieco trudniejszy.
>>
>>Taaak, bo takie potworki jak boost::mpl czy boost::spirit to są niezwykle
>>potrzebne
> 
> 
> Oh. Przeszkadza Ci, że ktoś myśli bardziej abstrakcyjnie niż łepsajty tego
> wymagają?

To nie jest myślenie abstrakcyjne. To jest marnowanie czasu swojego i innych 
  -- to jest jak IOCCC czy Perl Golf, tyle że szkodliwe, bo usiłuje być na 
serio.


> Pokaż mi takie cos jak MPL i SPIRIT w J i w Py.

W Py masz PyParsing.

Zamiast zatykającego kompilator i powolnego Spirita wolę użyć Antlr -- da mi 
kod i dla Javy i dla C++ i dla C# i dla Pythona. Szybszy i w kompilacji i w 
wykonaniu niż rzeźba w spiricie.

MPL to jest chore same w sobie.


> J wyciera sobie twarz XML i to równiutko, a jak chcesz mieć coś innego niż
> XML, to ci mówią, że ... hmm ... ę ... tego ... yyy ... ten tego,
> "poco ci coś innego niż XML?"
> 
> Parsery wszędzie pisze się parszywie.

Taaa, zwłaszcza w Ocamlu... Albo w Pythonie


> Więc Twój argument, że Spirit jest
> potworny jest nietrafiony.

Do parserów używa się odpowiednich narzędzi. Albo dobrego, a nie kulawego, 
języka :)


> Co do MPL. Np. w konstrukcji rozmytego algorytmu predykcyjnego mam kawałki z
> boost::mpl (dziś lepiej jest używać boost::fusion).
> 
> Jest to raczej poprawa czytelności, niż utrudnienie.

Co?!?! MPL i poprawa czytelności? Bez jaj!


>>>36 -- zgada się, tylko co to wnosi?
>>
>>W koślawym języku traci się kupę czasu na przeskakiwanie koślawości?
> 
> Ha, ha, ha. Tylko, że Pan F. pisze, że lubi C, a tam aż roi się o void* (*)
> (void*). I to boli nie na żarty.

W C wszystko jest explicite. W pewnych zastosowaniach to jest nawet istotne 
-- jak masz traceability w systemach krytycznych to to rzecz ułatwia.

W C++ już często tego explicite nie ma a syf i ubecja pozostały.


>>>38 -- mówił, że lubi C, a tam są te same problemy i na dodatek łata się
>>>je o wiele gorzej niż w C++.
>>
>>W C są wyjątki??? iteratory??? desytuktory????
> 
> Nie ma. Są za to inne kwiatki.

Te kwiatki są proste i ograniczone jak samo C.


> A w innych językach? Wystarczy sprawnie jak w
> dobrej szkole Troli zapodać na grupę post typu. "Słyszałem, że w języku XXX
> nie da się zrobić czegoś takiego jak YYY". Ach zaraz masz 1001 przepisów
> jak w dowolnym języku XXX można zrobić paskudniaczka. Do tego jeszcze
> chłopaki prześcigać się będą jak to wykonać najbardziej ekstremalnie -- bo
> przecież się da. Wszędzie się da kod spaskudzić.

Ale nie wszędzie kod najbardziej oczywisty jest kodem niebezpiecznym i 
niestylowym. To jest domena C++.


>>>40 -- no tak, a kto tak projektuje kod nawet w języku C. Co to za
>>>zwyczaj, aby obiekt kasował nie ten co go przydziela?
>>
>>To jest normalny zwyczaj. Tylko w nienormalnych językach to sprawia
>>problem :)
> 
> 
> Tak? A gdzie to jest normalny zwyczaj? Jeśli gdzieś są takie zwyczaje to
> kończy się to na posiadaniu GC.

I dobrze. GC znane jest od ponad 40 lat.

Zresztą C++ też już dosrasta do tego (w końcu). tr1 to już prawie standard, 
a w tr1 jest shared_ptr który od biedy pomaga.

> A ciekawie się dzieje, kiedy sam zaczniesz
> grzebać w tym co robi GC i np. rozgrzebiesz w GC to na czym pracuje GC.

?????

>>>... męczące jest zastanawianie się ile można brzydkich przykładów podać w
>>>dowolnym języku programowania ... bo w każdym to jest możliwe.
>>
>>Ale w innych językach tego problemu po prostu nie ma.
> 
> 
> Nie prawda. Zobacz sobie na to:
> 
> http://qsorix.jogger.pl/2006/12/14/java-jezyk-pelen-niespodzianek

I co to ma być? To jest poziom #define private public


> To jest właśnie poziom haków Pana F.

Nie, pan F. pokazuje rzeczywiste przypadki rzeczywistych kardynalnych błędów 
projektu samego języka, a to jest pokazanie nadużycia mechanizmu skąd inąd 
przydatnego.


> Zrobić coś nie całkiem tak, jak to się powinno robić, a potem gadać o
> wadach.

Co jest niecałkiem tak? UB, gdy masz głupi, prosty błąd użycia iteratora?


>>>47 -- chłopina rzutuje obiekt foo na bar a potem dziwi się, że "mu to nie
>>>działa".
>>
>>Co rzutuje? Przecież to jest "normalny" polimorfizm.
> 
> Tak? Jeśli tak piszesz normalne programy. To nie dziwię się, że uciekasz od
> C++.

Przykazywany jest wskaźnik na obiekt klasy pochodnej do funkcji oczekującej 
wskaźnika na obiekt klasy bazowej -- to jest *standardowe* użycie 
polimorfizmu. To, że funkcja oczekuje przekazania tablicy, tylko przygłupi, 
kulawy język nie miesza tablice ze wskaźnikami to jest to co jest.

To jest karygodny błąd języka. Tłumaczenie wielbicieli C++, żeby użyć 
ciężkiego wektora czy niewiele lżejszego, ale w ogóle nie należącego do 
języka boost::array jest poprostu żałosne.

Mamy język w którym są tablice, ale nie można ich używać, tylko jakiś 
cięzkich typów bibliotecznych, bo język jest spieprzony. To są Jaja na 
Resorach(tm).


>>Pokazana jedna z projektowych przypadłości C++ -- niekontrolowane
>>nakłądanie się na siebie cech, na skutek niedostatecznego przemyślenia
>>skutków dodawania określoncyh ficzerów -- połączenie odziedziczonego z C
>>pomieszania wskaźników z tablicami z obiektowym polimorfizmem rodzi
>>kaszanę.
> 
> C++ zawrapował C bardziej dosłownie niż to robią inne języki, np. CPython.
> Czy wadą CPythona jest to, że możesz też kod napisać w C?

Kod w C nie jest kodem w Pythonie. Kod w C często jest kodem w C++.


>>>Mi to w ogóle ten kod nie działa, a jak go poprawiłem to mi działa
>>>dobrze.
>>
>>Taaaak??!?!?!? O, to ciekawe!
> 
> Po prostu wystarczy ten kod napisać sensownie, a nie udowadniając tego co
> Pan F. chciał wykazać.

Pan F. zademonstorwał kardynalny błąd w samym środku języka.

pzdr
\SK
Re: Ciemna strona C++
#267662
Author: Jedrzej Dudkiewicz
Date: Fri, 09 Nov 2007 16:00
37 lines
2529 bytes
> Przykazywany jest wskaźnik na obiekt klasy pochodnej do funkcji 
> oczekującej wskaźnika na obiekt klasy bazowej -- to jest *standardowe* 
> użycie polimorfizmu. To, że funkcja oczekuje przekazania tablicy, tylko 
> przygłupi, kulawy język nie miesza tablice ze wskaźnikami to jest to co 
> jest.

Wydaje mi się, że o ile przykład pokazuje prawdziwy problem, to sam jest 
idiotyczny, tzn. strasznie wydumany. W C++, nawet gdyby tablice były 
obsługiwane prawidłowo, tj. nie byłoby rzutowania (niejawnego) wskaźnika 
na tablicę, to ten przykład chyba byłby ciągle marny:

class A {};
class B : public A {
public:
	void do_me() { };
};

B tablica[3];

void fun(A tablica[])
{
     tablica[0].do_me(); // <- co z tym?
}

Znaczy - trzebaby niejawnie jakoś konwertować to na wskaźniki... No nie 
wiem, jakaś porażka. Czyli jeszcze raz - o ile przedstawiony problem 
jest prawdziwy, to przykład jest całkiem z kosmosu - stąd łatwo się go 
czepiać.

> To jest karygodny błąd języka. Tłumaczenie wielbicieli C++, żeby użyć 
> ciężkiego wektora czy niewiele lżejszego, ale w ogóle nie należącego do 
> języka boost::array jest poprostu żałosne.

A co jest ciężkiego w vectorze? To nie zaczepka, tylko ciekawość, żeby 
nie było.

JD
Re: Ciemna strona C++
#267663
Author: Jedrzej Dudkiewicz
Date: Fri, 09 Nov 2007 16:05
26 lines
1679 bytes
Jedrzej Dudkiewicz wrote:
> na tablicę, to ten przykład chyba byłby ciągle marny:

Tak samo jak to, co napisałem :]

> class A {};

class A {
virtual void do_me() {}
};

> class B : public A {
> public:
>     void do_me() { };
> };
> 
> B tablica[3];
> 
> void fun(A tablica[])
> {
>     tablica[0].do_me(); // <- co z tym?
> }

Które do_me() będzie wywołane?

JD
Re: Ciemna strona C++
#267665
Author: Seweryn Habdank-Wojewódzki
Date: Fri, 09 Nov 2007 22:31
28 lines
1881 bytes
Witam

Jedrzej Dudkiewicz wrote:

> Wydaje mi się, że o ile przykład pokazuje prawdziwy problem,
> to sam jest idiotyczny, tzn. strasznie wydumany.

Właśnie o tym mówię.

> Znaczy - trzebaby niejawnie jakoś konwertować to na wskaźniki... No nie
> wiem, jakaś porażka.

Dlatego pisałem, że w jakimś wariancie Pan F. powinien użyć bar **, a nie
bar*.

>> To jest karygodny błąd języka. Tłumaczenie wielbicieli C++, żeby użyć
>> ciężkiego wektora czy niewiele lżejszego, ale w ogóle nie należącego do
>> języka boost::array jest poprostu żałosne.
> 
> A co jest ciężkiego w vectorze?

Waży 12 bajtów?

Pozdrawiam.

-- 
|\/\/|   Seweryn Habdank-Wojewódzki
 \/\/
Re: Ciemna strona C++
#267667
Author: Piotr Wyderski
Date: Fri, 09 Nov 2007 23:16
10 lines
1583 bytes
Seweryn Habdank-Wojewódzki wrote:

>> A co jest ciężkiego w vectorze?
>
> Waży 12 bajtów?

Alokuje. I zwalnia.

    Pozdrawiam
    Piotr Wyderski
Re: Ciemna strona C++
#267666
Author: Łukasz Krotowski
Date: Sat, 10 Nov 2007 00:29
14 lines
1535 bytes
Dnia 2007-11-09, Piotr Wyderski napisał:
> Seweryn Habdank-Wojewódzki wrote:
>
>>> A co jest ciężkiego w vectorze?
>>
>> Waży 12 bajtów?
>
> Alokuje. I zwalnia.

Ani nie alokuje, ani nie zwalnia. Używa alokatora -- najwyżej ten może
być ciężki.

-- 
Łukasz Krotowski | lukasz.krotowski_AT_gmail.com
Re: Ciemna strona C++
#267668
Author: Jedrzej Dudkiewicz
Date: Sat, 10 Nov 2007 00:52
15 lines
1770 bytes
Piotr Wyderski wrote:
> Seweryn Habdank-Wojewódzki wrote:
> 
>>> A co jest ciężkiego w vectorze?
>>
>> Waży 12 bajtów?
> 
> Alokuje. I zwalnia.

Czyli chodziloby najbardziej o to, ze gmera po pamieci i traci sie 
spatial locality, tak? Tylko ze jezeli chce sie miec spatial locality i 
bezpieczenstwo zakresu tablicy i tablice o zmiennym rozmiarze, to sie to 
robi bardzo, bardzo skomplikowane.

JD
Re: Ciemna strona C++
#267669
Author: Piotr Wyderski
Date: Sat, 10 Nov 2007 13:35
26 lines
2588 bytes
Jedrzej Dudkiewicz wrote:

> Czyli chodziloby najbardziej o to, ze gmera po pamieci i traci sie spatial 
> locality, tak?

Lokalność będzie OK, w końcu to jest owrapowana tablica.
Chodzi mi o bardzo duży koszt obsługi zarządzania pamięcią
-- nawet szybkie alokatory są powolne w porównaniu do
przydziału pamięci na stosie. Sprawia to, że z wektora (oraz
m.in. stringa) jest bardzo kiepski obiekt krótkożyjący (wynik
funkcji albo zmienna automatyczna w bloku), a jest to dość
częsty sposób jego użycia. Można dużo zyskać na wydajności
po zastąpieniu tych klas własnymi, dopasowanymi do konkretnych
potrzeb wynalazkami. Jeśli jednak wektor żyje długo, to
koszt jego użycia jest asymptotycznie równy zwykłej tablicy
i wydajnościowo jest w porządku.

> Tylko ze jezeli chce sie miec spatial locality i bezpieczenstwo
> zakresu tablicy i tablice o zmiennym rozmiarze, to sie to robi
> bardzo, bardzo skomplikowane.

"Jak się ktoś boi latać myśliwcem, to niech se
kupi bilet na RyanAir" (C) współpracownik. ;-)

    Pozdrawiam
    Piotr Wyderski
Re: Ciemna strona C++
#267670
Author: Łukasz Krotowski
Date: Sat, 10 Nov 2007 13:46
16 lines
1831 bytes
Dnia 2007-11-10, Piotr Wyderski napisał:
> Jedrzej Dudkiewicz wrote:
>
>> Czyli chodziloby najbardziej o to, ze gmera po pamieci i traci sie spatial 
>> locality, tak?
>
> Lokalność będzie OK, w końcu to jest owrapowana tablica.
> Chodzi mi o bardzo duży koszt obsługi zarządzania pamięcią
> -- nawet szybkie alokatory są powolne w porównaniu do
> przydziału pamięci na stosie. 

Dlaczego? W obu przypadkach alokacja sprowadza się do zwiększenia
pewnego wskaźnika.

-- 
Łukasz Krotowski | lukasz.krotowski_AT_gmail.com
Re: Ciemna strona C++
#267671
Author: Piotr Wyderski
Date: Sat, 10 Nov 2007 14:15
23 lines
2464 bytes
Łukasz Krotowski wrote:

> Dlaczego? W obu przypadkach alokacja sprowadza się do zwiększenia
> pewnego wskaźnika.

Ja mówię o grupowej alokacji "underlying storage",
a nie przydziale miejsca dla pojedynczego elementu.
Alokator jest wołany co najmniej tyle razy, ile
konstruktor i destruktor wektora. Jeśli ten wektor
jest tworzony i niszczony bardzo często (np. jako
zmienna automatyczna w pętli, niekoniecznie jawna),
to rezultaty są opłakane. Dlatego właśnie napisałem
sobie wektor początkowo alokujący na stosie i który
działa tylko dla typów prostych, więc nie woła
destruktorów. To ostatnie ograniczenie oczywiście
nie jest konieczne i da się napisac klasę ogólną
bez straty wydajności, dzięki specjalizacjom, ale
"premature generalization is the root of all evil", więc
nie chciałem tracić czasu na pisanie czegoś, czego
i tak nigdy nie użyję.

    Pozdrawiam
    Piotr Wyderski
Re: Ciemna strona C++
#267693
Author: Seweryn Habdank-Wojewódzki
Date: Sat, 10 Nov 2007 14:21
147 lines
3763 bytes
Witam

Piotr Wyderski wrote:

> Seweryn Habdank-Wojewódzki wrote:
> 
>>> A co jest ciężkiego w vectorze?
>>
>> Waży 12 bajtów?
> 
> Alokuje. I zwalnia.

OK. Masz 100% racji, ale w tym przypadku zawsze jest jakaś alokacja.

Poniżej ten sam kod napisany w J (działa). 
Pokaż mi, że potrafisz go napisać bez alokacji. Zwróć uwagę na to jak
wygląda linijka oznaczona /* ### */. Tam są "new B()", to jest alokacja.
Zarówno w J jak i w ++ polimorfizm uzyskuje się w sposób dynamiczny.
Zatem w tym konkretnym przypadku kiedy masz tablicę i chcesz, aby ona
zawiadywała obiektami polimorficznymi, musisz coś alokować.
Poniżej kodu J jest identyczny kod w ++ też działa.

Pozdrawiam.

/* ------------------- JAVA ------------------ */

public class A {
    
    public A() {
        i_ = 0;
    }
    
    public void m() {
        System.out.println(i_);
    }
    
    public int i_;
}

public class B extends A {
    
    public B() {
        super ();
        j_ = 0;
    }
    
    public void m() {
        System.out.println(j_);
        System.out.println(super.i_);
    }
    
    public int j_;
}

public class Test {

    public Test() {
    }
    
    public void test (A a[])
    {
        a[0].m();
        a[1].m();
        a[2].m();
    }
    
}

public class Main {
    
    public Main() {
    }
      
    public static void main(String[] args) {
        Test tester = new Test();
              
        /* ### */
        B barr[] = {new B(), new B(), new B()};
        tester.test (barr);
    }
    
}

/* --------------- C++ -------------------- */

#include <cstdio>

class A 
{
public:
    A() : i_ (0) {}
    A(int i) : i_ (i) {}

    virtual void m()
    {
        printf("%s %d\n", "A::m", i_);
    }

    virtual ~A(){}
    int i_;
};

class B : public A 
{
public:
    B() : A (0), j_ (0) {}
    B(int i, int j) : A (i), j_ (j) {}

    virtual void m()
    {
        printf("%s %d %d\n", "B::m", A::i_, j_);
    }

    virtual ~B(){}

    int j_;
};

void test (A & a)
{
    a.m();
}

//void test (A arr[3])
void test (A* arr[3])
{
    arr[0]->m();
    arr[1]->m();
    arr[2]->m();
}

int main()
{
    int const TAB_SIZE = 3;
    A* b_arr[TAB_SIZE];
    for (int i = 0; i < 3; ++i)
        b_arr[i] = new B();

    test (b_arr);

    for (int i = 0; i < TAB_SIZE; ++i)
        delete b_arr[i];
}

-- 
|\/\/|   Seweryn Habdank-Wojewódzki
 \/\/
Re: Ciemna strona C++
#267694
Author: Piotr Wyderski
Date: Sat, 10 Nov 2007 14:35
27 lines
2594 bytes
Seweryn Habdank-Wojewódzki wrote:

> OK. Masz 100% racji, ale w tym przypadku zawsze jest jakaś alokacja.

Jest, ale to nie musi oznaczać alokacji na stercie.

> Pokaż mi, że potrafisz go napisać bez alokacji.

Ja go nie potrafię napisać bez alokacji na stercie, bo to struktura
dynamiczna. Potrafię za to napisać go tak, by w typowym przypadku
liczba alokacji wynosiła 0. Wektory są zazwyczaj małe, więc mogę
sobie z góry przydzielić miejsce dla N elementów jako tablica w ciele
klasy i przejść na stertę dopiero po wyczerpaniu pojemności
wbudowanej tablicy. A jakie N jest dobre, to zależy od konkretnego
przypadku, znajdę je sobie uruchamiając program na typowych
danych i mnożąc wynik przez wzięty z sufitu "współczynnik
bezpieczeństwa". :-) Domyślnie mam 64 elementy, ale to parametr
szablonu, więc nie ma problemu z jego nadpisaniem.

> Zwróć uwagę na to jak wygląda linijka oznaczona /* ### */. Tam
> są "new B()", to jest alokacja.

Te alokacje się nie liczą, wektor o nich nie wie. Mnie chodzi
o coś takiego: std::vector<char>.

    Pozdrawiam
    Piotr Wyderski
Re: Ciemna strona C++
#267672
Author: Łukasz Krotowski
Date: Sat, 10 Nov 2007 15:04
21 lines
2215 bytes
Dnia 2007-11-10, Piotr Wyderski napisał:
> Łukasz Krotowski wrote:
>
>> Dlaczego? W obu przypadkach alokacja sprowadza się do zwiększenia
>> pewnego wskaźnika.
>
> Ja mówię o grupowej alokacji "underlying storage",
> a nie przydziale miejsca dla pojedynczego elementu.
> Alokator jest wołany co najmniej tyle razy, ile
> konstruktor i destruktor wektora. Jeśli ten wektor
> jest tworzony i niszczony bardzo często (np. jako
> zmienna automatyczna w pętli, niekoniecznie jawna),
> to rezultaty są opłakane.

Cały czas nie rozumiem. Każde zawołanie alokatora w takiej pętli to
będzie zwiększenie lub zmniejszenie jednego wskaźnika wskazującego na
wierzchołek zajętej pamięci w globalnej puli. W czym to jest gorsze od
alokacji na stosie (problem wątków na razie pomińmy)?

-- 
Łukasz Krotowski | lukasz.krotowski_AT_gmail.com
Re: Ciemna strona C++
#267673
Author: Piotr Wyderski
Date: Sat, 10 Nov 2007 15:15
15 lines
2187 bytes
Łukasz Krotowski wrote:

> Cały czas nie rozumiem. Każde zawołanie alokatora w takiej pętli to
> będzie zwiększenie lub zmniejszenie jednego wskaźnika wskazującego na
> wierzchołek zajętej pamięci w globalnej puli.

A gdzie Ty widziałeś taki alokator? Przecież to działa tylko
wtedy, gdy porządek zwalniania jest odwrotny względem
porządku przydziału, a globalnemu alokatorowi nie wolno
robić takich założeń. Alokatory kompaktujące, które
zapewne masz na myśli, są nie do wykorzystania w C++
-- to jest garbage collection.

    Pozdrawiam
    Piotr Wyderski
Re: Ciemna strona C++
#267674
Author: Łukasz Krotowski
Date: Sat, 10 Nov 2007 16:44
25 lines
2553 bytes
Dnia 2007-11-10, Piotr Wyderski napisał:
> Łukasz Krotowski wrote:
>
>> Cały czas nie rozumiem. Każde zawołanie alokatora w takiej pętli to
>> będzie zwiększenie lub zmniejszenie jednego wskaźnika wskazującego na
>> wierzchołek zajętej pamięci w globalnej puli.
>
> A gdzie Ty widziałeś taki alokator? Przecież to działa tylko
> wtedy, gdy porządek zwalniania jest odwrotny względem
> porządku przydziału, a globalnemu alokatorowi nie wolno
> robić takich założeń.

Hmmmmm...
Ale przecież cały czas rozmawiamy o różnicach alokacji dynamicznej w
stosunku do alokacji stosu. W takim przypadku porządek jest
zapewniony. OK, w przypadku std::vector<> problemem są metody
resize()/reserve(). I dlatego alokator musiałby być sprytniejszy (lub
mieć wsparcie kompilatora). Choć z drugiej strony, jeśli porównujemy z
tablicami na stosie powinniśmy wyłączyć możliwość zmiany rozmiaru. 

Niemniej jednak, dedykowany alokator dla obiektów o krótkim czasie życia
mógłby zapewnić alokację o wydajności porównywalnej do stosu.

-- 
Łukasz Krotowski | lukasz.krotowski_AT_gmail.com
Re: Ciemna strona C++
#267675
Author: Piotr Wyderski
Date: Sat, 10 Nov 2007 17:43
36 lines
3324 bytes
Łukasz Krotowski wrote:

> Ale przecież cały czas rozmawiamy o różnicach alokacji
> dynamicznej w stosunku do alokacji stosu. W takim
> przypadku porządek jest zapewniony.

Ale alokator tego nie wie. Sam wektor również nie zna kontekstu,
w jakim jest używany, więc nie może poinformować o nim alokatora
nawet, gdyby to było w jakiś sposób możliwe.

> Choć z drugiej strony, jeśli porównujemy z tablicami na
> stosie powinniśmy wyłączyć możliwość zmiany rozmiaru.

Sprzeciw, ja chcę mieć obiekt tymczasowy, dynamiczny i bardzo
wydajny. Gdybym potrzebował tablicy statycznej, to mam boost::array.

> Niemniej jednak, dedykowany alokator dla obiektów o krótkim czasie życia
> mógłby zapewnić alokację o wydajności porównywalnej do stosu.

Nie, bo dla alokatora nie długość życia obiektu ma znaczenie, lecz
porządek destrukcji. Ten porządek nie jest znany i dlatego nie można
robić założeń na jego temat. Oczywiście, szybki alokator do obiektów
o krótkim czasie życia może być jedynie kilkadziesiąt razy wolniejszy
niż alokacja stosowa, ale nie znając kolejności destrukcji to nie jest
szybki alokator do obiektów tymczasowych, lecz po prostu szybki
alokator uniwersalny. A jeśli zakładasz porządek LIFO i alokator ma
tego świadomość, to to nie będzie konstrukcja porównywalna do
stosu, tylko stos we własnej osobie, istniejący niezależnie duplikat
systemowej struktury danych. Można się więc takiego alokatora
bez żalu pozbyć i koncepcyjnie zintegrować ze strukturą danych.

    Pozdrawiam
    Piotr Wyderski

-- 
"Non sunt multiplicanda entia sine necessitate"
Re: Ciemna strona C++ -- slajd 47, rozwiązanie z uzyciem polimorfizmu statycznego
#267664
Author: Seweryn Habdank-Wojewódzki
Date: Sat, 10 Nov 2007 17:45
39 lines
1922 bytes
Witam

Jedrzej Dudkiewicz wrote:

> class A {
> virtual void do_me() {}
> };
> 
>> class B : public A {
>> public:
>>     void do_me() { };
>> };
>> 
>> B tablica[3];
>> 
>> void fun(A tablica[])
>> {
>>     tablica[0].do_me(); // <- co z tym?
>> }
> 
> Które do_me() będzie wywołane?

Napisz fun tak:

template <typename T>
void fun(T* tablica)
{
        tablica[0].do_me();
}

To działa poprawnie, bo nie ma tego głupkowatego rzutowania na A, tylko
kompilator decyduje o tym jaki typ najlepiej pasuje do wymaganego i taki
kod jest generowany.

Pozdrawiam.

-- 
|\/\/|   Seweryn Habdank-Wojewódzki
 \/\/
Re: Ciemna strona C++
#267684
Author: Seweryn Habdank-Wojewódzki
Date: Sat, 10 Nov 2007 17:51
15 lines
1804 bytes
Witam

Łukasz Krotowski wrote:

> Niemniej jednak, dedykowany alokator dla obiektów o krótkim czasie życia
> mógłby zapewnić alokację o wydajności porównywalnej do stosu.

Albo wręcz korzystać z wbudowanych funkcji alokujących na stosie, np. w
linuxie alloca.

Pozdrawiam.

-- 
|\/\/|   Seweryn Habdank-Wojewódzki
 \/\/
Re: Ciemna strona C++
#267685
Author: Piotr Wyderski
Date: Sat, 10 Nov 2007 18:03
21 lines
2607 bytes
Seweryn Habdank-Wojewódzki wrote:

> Albo wręcz korzystać z wbudowanych funkcji alokujących na stosie, np. w
> linuxie alloca.

Panowie, ale PO CO? :-)))

Wbudowanie w wektor (czy string) niewielkiego bufora od ręki
rozwiązuje _wszystkie_ problemy: mamy alokację i dealokację
początkową o _zerowym_ koszcie (wielkość jest wyliczana w
czasie kompilacji), rozwiązanie jest stuprocentowo wielowątkowe,
lokalnośc ma znakomitą (dla małych danych jedna linia cache, a nie
dwie, jak w std::vector), nie wymaga osobnego wpisu w TLB
(bo posługuje się stosowym) i do tego jest całkowicie przenośne.
Jedyna wada to pewien niewielki narzut na zajętość pamięci, gdy
ktoś dobierze złą pojemność bufora wewnętrznego -- w przypadku
obiektów tymczasowych rzecz kompletnie bez znaczenia, bo
granulacja alokacji pamięci dla stosu to co najmniej strona.

    Pozdrawiam
    Piotr Wyderski
Re: Ciemna strona C++
#267676
Author: Łukasz Krotowski
Date: Sat, 10 Nov 2007 18:19
62 lines
4103 bytes
Dnia 2007-11-10, Piotr Wyderski napisał:
> Łukasz Krotowski wrote:
>
>> Ale przecież cały czas rozmawiamy o różnicach alokacji
>> dynamicznej w stosunku do alokacji stosu. W takim
>> przypadku porządek jest zapewniony.
>
> Ale alokator tego nie wie. Sam wektor również nie zna kontekstu,
> w jakim jest używany, więc nie może poinformować o nim alokatora
> nawet, gdyby to było w jakiś sposób możliwe.

Programista to wie i może użyć vector<T, stack_allocator> lub
vector<T>. 

>> Choć z drugiej strony, jeśli porównujemy z tablicami na
>> stosie powinniśmy wyłączyć możliwość zmiany rozmiaru.
>
> Sprzeciw, ja chcę mieć obiekt tymczasowy, dynamiczny i bardzo
> wydajny. Gdybym potrzebował tablicy statycznej, to mam boost::array.
>
>> Niemniej jednak, dedykowany alokator dla obiektów o krótkim czasie życia
>> mógłby zapewnić alokację o wydajności porównywalnej do stosu.
>
> Nie, bo dla alokatora nie długość życia obiektu ma znaczenie, lecz
> porządek destrukcji. Ten porządek nie jest znany i dlatego nie można
> robić założeń na jego temat. Oczywiście, szybki alokator do obiektów
> o krótkim czasie życia może być jedynie kilkadziesiąt razy wolniejszy
> niż alokacja stosowa, ale nie znając kolejności destrukcji to nie jest
> szybki alokator do obiektów tymczasowych, lecz po prostu szybki
> alokator uniwersalny.

Serio, serio?
#v+
// gdzieś, lokalnie w kodzie
memory_pool local_pool(LOCAL_POOL_SIZE);
do_not_deallocate_allocator::set_pool(local_pool);

typedef std::vector<int, do_not_deallocate_allocator> local_int_vector_t;
local_int_vector_t vec1;
// ...
// po zakończeniu pracy
// explicite, równie dobrze może być RAII
local_pool.release();
#v-

W takim przypadku alokacja będzie porównywalna ze stosową, a dealokacja
szybsza. Oczywiście długość życia obiektów ma znaczenie (chyba, że masz
wyznaczoną funkcję zajętości pamięci dla całego programu, wtedy w ogóle
nie musisz martwić się o zwalnianie -- o ile tylko pamięci fizycznej
starczy).

> A jeśli zakładasz porządek LIFO i alokator ma
> tego świadomość, to to nie będzie konstrukcja porównywalna do
> stosu, tylko stos we własnej osobie, istniejący niezależnie duplikat
> systemowej struktury danych. Można się więc takiego alokatora
> bez żalu pozbyć i koncepcyjnie zintegrować ze strukturą danych.

Kwestia podejścia, dla mnie oddzielenie mechanizmu przydziału pamięci od
kontenera przechowującego obiekty jest dobrym pomysłem.

-- 
Łukasz Krotowski | lukasz.krotowski_AT_gmail.com
Re: Ciemna strona C++
#267686
Author: Łukasz Krotowski
Date: Sat, 10 Nov 2007 18:28
32 lines
2883 bytes
Dnia 2007-11-10, Piotr Wyderski napisał:
> Seweryn Habdank-Wojewódzki wrote:
>
>> Albo wręcz korzystać z wbudowanych funkcji alokujących na stosie, np. w
>> linuxie alloca.
>
> Panowie, ale PO CO? :-)))

Bo można. ;)

> Wbudowanie w wektor (czy string) niewielkiego bufora od ręki
> rozwiązuje _wszystkie_ problemy: mamy alokację i dealokację
> początkową o _zerowym_ koszcie (wielkość jest wyliczana w
> czasie kompilacji), rozwiązanie jest stuprocentowo wielowątkowe,
> lokalnośc ma znakomitą (dla małych danych jedna linia cache, a nie
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> dwie, jak w std::vector), nie wymaga osobnego wpisu w TLB
  ^^^^^^^^^^^^^^^^^^^^^^^
> (bo posługuje się stosowym) i do tego jest całkowicie przenośne.
> Jedyna wada to pewien niewielki narzut na zajętość pamięci, gdy
> ktoś dobierze złą pojemność bufora wewnętrznego -- w przypadku
> obiektów tymczasowych rzecz kompletnie bez znaczenia, bo
> granulacja alokacji pamięci dla stosu to co najmniej strona.

Podkreślone rzeczywiście jest fajne. Nie chcemy krytykować Twojej
optymalizacji dla małych tablic. Ale nie krytykuj naszych alokatorów
które też potrafią ładnie działać.

Pij i pozwól pić innym. Jak mawiają mądrzy ludzie. ;)

-- 
Łukasz Krotowski | lukasz.krotowski_AT_gmail.com
Re: Ciemna strona C++
#267677
Author: Seweryn Habdank-Wojewódzki
Date: Sat, 10 Nov 2007 19:13
32 lines
2473 bytes
Witam

Łukasz Krotowski wrote:

> Serio, serio?
> #v+
> // gdzieś, lokalnie w kodzie
> memory_pool local_pool(LOCAL_POOL_SIZE);
> do_not_deallocate_allocator::set_pool(local_pool);
> 
> typedef std::vector<int, do_not_deallocate_allocator> local_int_vector_t;
> local_int_vector_t vec1;
> // ...
> // po zakończeniu pracy
> // explicite, równie dobrze może być RAII
> local_pool.release();
> #v-
> 
> W takim przypadku alokacja będzie porównywalna ze stosową, a dealokacja
> szybsza. Oczywiście długość życia obiektów ma znaczenie (chyba, że masz
> wyznaczoną funkcję zajętości pamięci dla całego programu, wtedy w ogóle
> nie musisz martwić się o zwalnianie -- o ile tylko pamięci fizycznej
> starczy).

Dorzucam jeszcze, aby stosowna tablica była oznaczona jako static, to często
też przyspiesza -- przyczym trzeba być ostrożnym.

Pozdrawiam.

-- 
|\/\/|   Seweryn Habdank-Wojewódzki
 \/\/
Re: Ciemna strona C++
#267688
Author: Seweryn Habdank-Wojewódzki
Date: Sat, 10 Nov 2007 19:19
34 lines
2740 bytes
Witam

Piotr Wyderski wrote:

> Seweryn Habdank-Wojewódzki wrote:
> 
>> Albo wręcz korzystać z wbudowanych funkcji alokujących na stosie, np. w
>> linuxie alloca.
> 
> Panowie, ale PO CO? :-)))
> 
> Wbudowanie w wektor (czy string) niewielkiego bufora od ręki
> rozwiązuje _wszystkie_ problemy: mamy alokację i dealokację
> początkową o _zerowym_ koszcie (wielkość jest wyliczana w
> czasie kompilacji), rozwiązanie jest stuprocentowo wielowątkowe,
> lokalnośc ma znakomitą (dla małych danych jedna linia cache, a nie
> dwie, jak w std::vector), nie wymaga osobnego wpisu w TLB
> (bo posługuje się stosowym) i do tego jest całkowicie przenośne.

Tak ale TO również jest w gestii alokatora. Możesz mieć taki alokator, 
który od razu tworzy bufor. Coś około tego jest opisane u A.A. przy
omawianiu alokatora małych obiektów.

> Jedyna wada to pewien niewielki narzut na zajętość pamięci, gdy
> ktoś dobierze złą pojemność bufora wewnętrznego

To nie jest żadna wada. Chyba, że uznajemy że niedouczeni tez mogą tak
programować i założymy, że zawsze będą źle określać rozmiar.

Pozdrawiam.

-- 
|\/\/|   Seweryn Habdank-Wojewódzki
 \/\/
Re: Ciemna strona C++
#267687
Author: Piotr Wyderski
Date: Sat, 10 Nov 2007 19:23
26 lines
2640 bytes
Łukasz Krotowski wrote:

>> Panowie, ale PO CO? :-)))
>
> Bo można. ;)

"Wszystko wolno, ale nie wszystko przynosi korzyść" ;-)

> Nie chcemy krytykować Twojej optymalizacji dla małych tablic.

Krytykujcie do woli, może istotnie coś przeoczyłem. :-)
Ale zajmowałem się tym problemem dość gruntownie
i doszedłem m.in. do przedstawionych wniosków. Były
jeszcze takie o dużych możliwościach oSIMDowania
własnego kontenerka, ale to nie ma związku z tematem.
Sprawdziłem to w praktyce (tzn. przemysłowym produkcie,
a nie jakimś samplu) i wyniki były bardzo dobre. No to
reklamuję, bo to ogólna technika, a nie wyspecjalizowany
pomysł, który wolę zachować do własnej wiadomości.

> Ale nie krytykuj naszych alokatorów które też potrafią ładnie działać.

Zatem będę je opiewał heksametrem. ;-)

    Pozdrawiam
    Piotr Wyderski
Re: Ciemna strona C++
#267689
Author: Piotr Wyderski
Date: Sat, 10 Nov 2007 19:33
25 lines
2778 bytes
Seweryn Habdank-Wojewódzki wrote:

> Tak ale TO również jest w gestii alokatora.

Seweryn, na litość Nieistniejącego: nie jest! Aby było, to buforek
musi być fizyczną częścią obiektu nadrzędnego, np. wektora.
W wielu implementacjach STL wektor istotnie dziedziczy po
alokatorze, więc _tam_ się na upartego da, ale gwarancji na
takie dziedziczenie (o ile wiem -- niech badacze Pisma poprawią,
jeśli się mylę) nie ma. Mój wektor odpowiednią gwarancję daje.

> Możesz mieć taki alokator, który od razu tworzy bufor.

No przecież mam taki bufor.

>> Jedyna wada to pewien niewielki narzut na zajętość pamięci, gdy
>> ktoś dobierze złą pojemność bufora wewnętrznego
>
> To nie jest żadna wada. Chyba, że uznajemy że niedouczeni tez mogą tak
> programować i założymy, że zawsze będą źle określać rozmiar.

Uważam podobnie, ale elementarna uczciwość nakazywała o tym wspomnieć.

    Pozdrawiam
    Piotr Wyderski
Re: Ciemna strona C++
#267678
Author: Piotr Wyderski
Date: Sat, 10 Nov 2007 19:48
33 lines
2913 bytes
Łukasz Krotowski wrote:

> // gdzieś, lokalnie w kodzie
> memory_pool local_pool(LOCAL_POOL_SIZE);
> do_not_deallocate_allocator::set_pool(local_pool);

A skąd sobie weźmiesz adres puli w miejscu użycia?
Będzie globalna, czy będziesz przepychał to jako parametr?
Bo pierwsze rozwiązanie padnie w kodzie wielowątkowym,
a drugie będzie "wydajne inaczej".

> W takim przypadku alokacja będzie porównywalna ze stosową

OK.

> a dealokacja szybsza.

Nie widzę żadnego powodu, by była szybsza. Dealokacja stosowa
składa się z _jednej_ instrukcji: addl, $size, %esp. Kompilator może
zgrupować takie zwolnienia w jedno add, sumując ich rozmiary
i z prawdopodobieństwem graniczącym z pewnością to zrobi, bo
taka optymalizacja jest trywialna. Jak się mocno postarasz
i będziesz miał szczęście, to dogonisz wydajność dealokacji
stosowej, ale "you've got to ask yourself a question: Do I feel
lucky? Well, do ya punk?" ;-)))

> Oczywiście długość życia obiektów ma znaczenie

Jak najbardziej, ale akurat nie w tym rozwiązaniu,
które z Sewerynem próbujecie mi sprzedać. :-)

    Pozdrawiam
    Piotr Wyderski
Re: Ciemna strona C++
#267679
Author: Łukasz Krotowski
Date: Sat, 10 Nov 2007 20:13
51 lines
3508 bytes
Dnia 2007-11-10, Piotr Wyderski napisał:
> Łukasz Krotowski wrote:
>
>> // gdzieś, lokalnie w kodzie
>> memory_pool local_pool(LOCAL_POOL_SIZE);
>> do_not_deallocate_allocator::set_pool(local_pool);
>
> A skąd sobie weźmiesz adres puli w miejscu użycia?
> Będzie globalna, czy będziesz przepychał to jako parametr?
> Bo pierwsze rozwiązanie padnie w kodzie wielowątkowym,
> a drugie będzie "wydajne inaczej".

Globalna. W przypadku wątków w TLS. Dla uproszczenia możemy założyć, że
alokator wielowątkowy można zastąpić wieloma instancjami alokatora
jednowątkowego w TLS.

>> W takim przypadku alokacja będzie porównywalna ze stosową
>
> OK.
>
>> a dealokacja szybsza.
>
> Nie widzę żadnego powodu, by była szybsza. Dealokacja stosowa
> składa się z _jednej_ instrukcji: addl, $size, %esp. Kompilator może
> zgrupować takie zwolnienia w jedno add, sumując ich rozmiary
> i z prawdopodobieństwem graniczącym z pewnością to zrobi, bo
> taka optymalizacja jest trywialna. Jak się mocno postarasz
> i będziesz miał szczęście, to dogonisz wydajność dealokacji
> stosowej, ale "you've got to ask yourself a question: Do I feel
> lucky? Well, do ya punk?" ;-)))

Hmm, jak pewnie się domyśliłeś dealokacja w do_not_deallocate_allocator
składa się z zera instrukcji. A powyższej optymalizacji opowiada jedno
wywołanie local_pool.release(). Czyli, jeśli kompilator nie
zoptymalizuje dobrze albo przeciągnę sobie życie local_pool przez więcej
niż jedno wywołanie funkcji to będę szybszy. (*)

>> Oczywiście długość życia obiektów ma znaczenie
>
> Jak najbardziej, ale akurat nie w tym rozwiązaniu,
> które z Sewerynem próbujecie mi sprzedać. :-)

Alokatory, alokatory! Trzy pięćdziesiąt za mendel!
BP, NMSP.


(*) Przekomarzanie się o kilka instrukcji. Ech, słodkie, sobotnie
dyskusje usnetowe. ;)

-- 
Łukasz Krotowski | lukasz.krotowski_AT_gmail.com
Re: Ciemna strona C++
#267680
Author: Piotr Wyderski
Date: Sat, 10 Nov 2007 21:03
39 lines
3315 bytes
Łukasz Krotowski wrote:

> Globalna. W przypadku wątków w TLS. Dla uproszczenia możemy założyć, że
> alokator wielowątkowy można zastąpić wieloma instancjami alokatora
> jednowątkowego w TLS.

Dobrze kombinujesz, tylko jest jeden problem: dostęp do zmienych
w TLS jest względnie powolny, jeśli opierasz się na API systemowym.
Wymyślenie naprawdę szybkich TLSów, działających bez wsparcia
API na głównej ścieżce zajęło mi sporo czasu i wynik jest dość
nietrywialny. Działa od kilku lat. Ale istotnie, bardzo szybkie TLSy
to kluczowy element współczesnego alokatora.

> Hmm, jak pewnie się domyśliłeś dealokacja w do_not_deallocate_allocator
> składa się z zera instrukcji.

To ja nie rozumiem, jak to ma działać. Dla każdego ciągu
wektorów osobna pula? Bez jaj. :-)

> albo przeciągnę sobie życie local_pool przez więcej
> niż jedno wywołanie funkcji to będę szybszy. (*)

Nie nadążam. Masz darmowe budowanie rekordów aktywacji?
Ech, kombinujecie, Panocku, jak koń pod górę.

> (*) Przekomarzanie się o kilka instrukcji.

No nie takie kilka, już się TLSy zaczęły pojawiac na horyzoncie. :-)
A poza tym akurat w moim zastosowaniu te kilka instrukcji było
istotne, formater znacznie przyspieszył po przejściu z mojego i tak
zoptymalizowanego alokatora w std::vector na kontener "stosowy";
o przypadku standardowego alokatora to szkoda gadać.

> Ech, słodkie, sobotnie dyskusje usnetowe. ;)

:-)

    Pozdrawiam
    Piotr Wyderski
Re: Ciemna strona C++
#267690
Author: Seweryn Habdank-Wojewódzki
Date: Sat, 10 Nov 2007 21:38
26 lines
2528 bytes
Witam

Piotr Wyderski wrote:

> Mój wektor odpowiednią gwarancję daje.

Ech. Ty zawsze masz swoje rozwiązania :-D.

Ale rozumiem, że to nie są zwykłe tablice. Pytam, bo od nich wyszła
dyskusja.

Czyli masz cały swój kontener zrobiony "from scratch". To jest bardzo dobre
rozwiązanie. Ale ma "wadę" znowu ktoś może powiedzieć, że w ++ każdy pisze
swoje i to jest niekompatybilne z innymi kontenerami ;-). Ciekawi mnie jak
to jest, jaka jest psychologia następującego zjawiska. W Py jest generalnie
1 (słownie jeden) kontener typu wektor/lista/deque, drugi to słownik. W J
jest trochę kontenerów, ale też nie jest jakaś zatrważająca liczba. W ++
nie dość, że kontenerów w STL jest trochę, to jeszcze każdy pisze pod
siebie. Jak to jest, że jednym wystarczy to że fabryka daje mało, a inni
chcą mieć tunnig pod siebie.

Pozdrawiam.

-- 
|\/\/|   Seweryn Habdank-Wojewódzki
 \/\/
Re: Ciemna strona C++
#267691
Author: Piotr Wyderski
Date: Sat, 10 Nov 2007 22:22
39 lines
3161 bytes
Seweryn Habdank-Wojewódzki wrote:

> Ech. Ty zawsze masz swoje rozwiązania :-D.

;-)))

> Ale rozumiem, że to nie są zwykłe tablice.

To działa prawie jak std::vector<T> dla T będącego typem prostym.
Służy m.in. do szybkiego składania napisów znak po znaku, w czym
string wydajnościowo jest bardzo słaby.

> Czyli masz cały swój kontener zrobiony "from scratch".

Całkowicie. Ale wektora oczywiście też używam -- tam, gdzie
jest dla niego odpowiednie miejsce, w tym żyje dostatecznie długo.

> Ale ma "wadę" znowu ktoś może powiedzieć, że w ++ każdy pisze
> swoje i to jest niekompatybilne z innymi kontenerami ;-).

Niekompatybilne z czym? Bo z moimi potrzebami rozwiązanie
to jest stuprocentowo kompatybilne. :-) A jak mi się coś nie
podoba, to sobie je zmieniam/rozszerzam.

> W ++ nie dość, że kontenerów w STL jest trochę, to jeszcze każdy
> pisze pod siebie.

Bo biblioteka standardowa jest dość dziwna. Z jednej strony
oferuje dużą konfigurowalność, a z drugiej nakarmienie
basic_ostream własnymi traitsami powoduje, że nie da się
go nigdzie użyć w miejscu std::ostream...

> Jak to jest, że jednym wystarczy to że fabryka daje
> mało, a inni chcą mieć tunnig pod siebie.

Pisałem Ci ostatnio o krawcach. :-)

    Pozdrawiam
    Piotr Wyderski
Re: Ciemna strona C++
#267681
Author: Łukasz Krotowski
Date: Sat, 10 Nov 2007 22:33
55 lines
4087 bytes
Dnia 2007-11-10, Piotr Wyderski napisał:
> Łukasz Krotowski wrote:
>> Globalna. W przypadku wątków w TLS. Dla uproszczenia możemy założyć, że
>> alokator wielowątkowy można zastąpić wieloma instancjami alokatora
>> jednowątkowego w TLS.
>
> Dobrze kombinujesz, tylko jest jeden problem: dostęp do zmienych
> w TLS jest względnie powolny, jeśli opierasz się na API systemowym.
> Wymyślenie naprawdę szybkich TLSów, działających bez wsparcia
> API na głównej ścieżce zajęło mi sporo czasu i wynik jest dość
> nietrywialny. Działa od kilku lat. Ale istotnie, bardzo szybkie TLSy
> to kluczowy element współczesnego alokatora.

Pewnie masz rację. Ale jeszcze nie zajmowałem się TLS na takim poziomie.
Zazwyczaj __thread w gcc mi wystarcza (plus to co jest w WinAPI,
przynajmniej do czasu aż wyjdzie stabilne gcc4 dla win32).

Mówiąc zupełnie szczerze, ostatnimi czasy wąskim gardłem są dla mnie
dyski i baza.

>> Hmm, jak pewnie się domyśliłeś dealokacja w do_not_deallocate_allocator
>> składa się z zera instrukcji.
>
> To ja nie rozumiem, jak to ma działać. Dla każdego ciągu
> wektorów osobna pula? Bez jaj. :-)

Nie. Załóżmy, że masz jakiś kawałek programu który działa na pewnej,
znanej ilości pamięci (stałej, bądź jako funkcja wejścia). Wtedy możesz,
z nonszalanckim ,,a co mi tam'', wszystkie kontenery z tego kawałka
programu przestawić na alokator który tylko alokuje. A po zakończeniu,
jednym pool.release() zwolnić całą pamięć.

To nie dotyczy tylko wektorów. A zaleta jest taka, że nie musisz dbać o
kolejność poszczególnych alokacji i dealokacji.

>> albo przeciągnę sobie życie local_pool przez więcej
>> niż jedno wywołanie funkcji to będę szybszy. (*)
>
> Nie nadążam. Masz darmowe budowanie rekordów aktywacji?
> Ech, kombinujecie, Panocku, jak koń pod górę.

Ja też nie nadążam. Skąd Ci się tutaj wzięły rekordy aktywacji?

>> (*) Przekomarzanie się o kilka instrukcji.
>
> No nie takie kilka, już się TLSy zaczęły pojawiac na horyzoncie. :-)
> A poza tym akurat w moim zastosowaniu te kilka instrukcji było
> istotne, formater znacznie przyspieszył po przejściu z mojego i tak
> zoptymalizowanego alokatora w std::vector na kontener "stosowy";
> o przypadku standardowego alokatora to szkoda gadać.

Formater? Wysoko-wydajny formater? Czego?

-- 
Łukasz Krotowski | lukasz.krotowski_AT_gmail.com
Re: Ciemna strona C++
#267682
Author: Piotr Wyderski
Date: Sat, 10 Nov 2007 23:02
52 lines
3684 bytes
Łukasz Krotowski wrote:

> Mówiąc zupełnie szczerze, ostatnimi czasy wąskim gardłem są dla mnie
> dyski i baza.

Na interfejsach do baz się zupełnie nie znam, ale w przypadku dysków
polecam tryb asynchroniczny oparty na completion ports oraz wyłączenie
cache'owania plików.

> Nie. Załóżmy, że masz jakiś kawałek programu który działa na pewnej,
> znanej ilości pamięci (stałej, bądź jako funkcja wejścia). Wtedy możesz,
> z nonszalanckim ,,a co mi tam'', wszystkie kontenery z tego kawałka
> programu przestawić na alokator który tylko alokuje. A po zakończeniu,
> jednym pool.release() zwolnić całą pamięć.

No ale ja nie wiem, ile pamięci mi będzie potrzeba. Wiem tylko,
ile dla typowych danych powinno wystarczyć. Jeśli będzie więcej,
to całość dalej ma działać poprawnie. Nie bardzo widzę też, jak
Twoja propozycja niezwalniająca zachowa się w takim przypadku:

    for(std::size_t i = 0; i < N; ++i) {

        fn();
    }

std::size_t fn() {

     std::vector<char, my_allocator> v;
      ...
      return v.size();
}

>>> albo przeciągnę sobie życie local_pool przez więcej
>>> niż jedno wywołanie funkcji to będę szybszy. (*)
>>
>> Nie nadążam. Masz darmowe budowanie rekordów aktywacji?
>> Ech, kombinujecie, Panocku, jak koń pod górę.
>
> Ja też nie nadążam. Skąd Ci się tutaj wzięły rekordy aktywacji?

No skoro zamierzasz przekazywać wskaźnik na local_pool
między funkcjami, to musisz go uczynić ich parametrem, a co
za tym idzie budować rekordy aktywacji go zawierające przy
każdym wywołaniu.

> Formater? Wysoko-wydajny formater? Czego?

Wielu różnych typów danych, ale tutaj głównie postaci
tekstowej liczb stałoprzecinkowej wielokrotnej precyzji.

    Pozdrawiam
    Piotr Wyderski
Re: Ciemna strona C++
#267683
Author: Łukasz Krotowski
Date: Sat, 10 Nov 2007 23:53
48 lines
3812 bytes
Dnia 2007-11-10, Piotr Wyderski napisał:
> Łukasz Krotowski wrote:
>> Mówiąc zupełnie szczerze, ostatnimi czasy wąskim gardłem są dla mnie
>> dyski i baza.
>
> Na interfejsach do baz się zupełnie nie znam, ale w przypadku dysków
> polecam tryb asynchroniczny oparty na completion ports oraz wyłączenie
> cache'owania plików.

O nie, nie przerobię obecnego rozwiązania na IOCP jeśli _naprawdę_ nie
będę musiał. Zbyt duża komplikacja, konieczność utrzymywania rozłącznych
mechanizmów dla Win32 i Linuksa itp. Nie opłaca się. ;)

>> Nie. Załóżmy, że masz jakiś kawałek programu który działa na pewnej,
        ^^^^^^^^^^^
>> znanej ilości pamięci (stałej, bądź jako funkcja wejścia). Wtedy możesz,
>> z nonszalanckim ,,a co mi tam'', wszystkie kontenery z tego kawałka
>> programu przestawić na alokator który tylko alokuje. A po zakończeniu,
>> jednym pool.release() zwolnić całą pamięć.
>
> No ale ja nie wiem, ile pamięci mi będzie potrzeba. Wiem tylko,
> ile dla typowych danych powinno wystarczyć. Jeśli będzie więcej,
> to całość dalej ma działać poprawnie.

Czyli Twoja sytuacja nie spełnia wymaganych założeń (podkreślone).
Pisałem o sytuacji gdy wiesz ile pamięci potrzeba. Np. wiesz, że
przetwarzasz jednorazowo jeden obraz. Każdy z obrazów ma ściśle
określone wymiary.

>>>> albo przeciągnę sobie życie local_pool przez więcej
>>>> niż jedno wywołanie funkcji to będę szybszy. (*)
>>>
>>> Nie nadążam. Masz darmowe budowanie rekordów aktywacji?
>>> Ech, kombinujecie, Panocku, jak koń pod górę.
>>
>> Ja też nie nadążam. Skąd Ci się tutaj wzięły rekordy aktywacji?
>
> No skoro zamierzasz przekazywać wskaźnik na local_pool
> między funkcjami, to musisz go uczynić ich parametrem, a co
> za tym idzie budować rekordy aktywacji go zawierające przy
> każdym wywołaniu.

Nie, wskaźnik (w rzeczywistości referencja) na local_pool jest ustawiona
raz, jako globalna zmienna w alokatorze. A alokator używany jest w wielu
funkcjach.

-- 
Łukasz Krotowski | lukasz.krotowski_AT_gmail.com
Re: Ciemna strona C++
#267692
Author: Jedrzej Dudkiewicz
Date: Mon, 12 Nov 2007 07:04
28 lines
2467 bytes
Piotr Wyderski wrote:
> Jedrzej Dudkiewicz wrote:
> 
>> Czyli chodziloby najbardziej o to, ze gmera po pamieci i traci sie 
>> spatial locality, tak?
> 
> Lokalność będzie OK, w końcu to jest owrapowana tablica.
> Chodzi mi o bardzo duży koszt obsługi zarządzania pamięcią
> -- nawet szybkie alokatory są powolne w porównaniu do
> przydziału pamięci na stosie. Sprawia to, że z wektora (oraz
> m.in. stringa) jest bardzo kiepski obiekt krótkożyjący (wynik
> funkcji albo zmienna automatyczna w bloku), a jest to dość
> częsty sposób jego użycia. 

A, dobra, faktycznie.

>> Tylko ze jezeli chce sie miec spatial locality i bezpieczenstwo
>> zakresu tablicy i tablice o zmiennym rozmiarze, to sie to robi
>> bardzo, bardzo skomplikowane.
> 
> "Jak się ktoś boi latać myśliwcem, to niech se
> kupi bilet na RyanAir" (C) współpracownik. ;-)

No tak, no tak, źle napisałem (była 2 w nocy) - nie chodzi o to, że 
skomplikowane, tylko ciężka się ta tablica robi. Znacznie cięższa od 
vector<>.

JD
Re: Ciemna strona C++
#267695
Author: Sebastian Kaliszewski
Date: Mon, 12 Nov 2007 16:46
13 lines
1616 bytes
Piotr Wyderski wrote:
>>> A co jest ciężkiego w vectorze?
>>
>> Waży 12 bajtów?
> 
> Alokuje. I zwalnia.

I robi to w arbitralny, niekontrolowany sposób.

I kopiuje (po to żeby zaraz oryginał odstrzelić).

pzdr
\SK
Page 1 of 10 • 486 total messages
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads