Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Ile razy wystąpiła dana liczba w tekście?

Ostatnio zmodyfikowano 2016-03-11 16:41
Autor Wiadomość
carlosmay
» 2016-03-08 20:05:02
@carlosmay z twoim kodem jest problem ponieważ na końcu linii nie ma przecinka.
Nie zwróciłem na niego uwagi. Sorki.
C/C++
int wyst[ 49 ] = { 0 };
while( fin >> liczba ) {
    ++wyst[ liczba - 1 ];
    fin.get();
}
for( size_t i = 0; i < 49; ++i ) {
    std::cout << "Liczba " <<( i + 1 ) << " wystąpiła w pliku " << wyst[ i ] << " razy.\n";
}
P-145750
michal11
» 2016-03-08 20:19:47
@Kaikso To, że jest inline wcale nie oznacza, że funkcja taka rzeczywiście będzie.

Może lepsze byłoby w tym przypadku constexpr ?
P-145753
Kaikso
» 2016-03-08 20:37:48
Wiem jak to działa. A żeby kompilator z tak małego kodu nie zrobił faktycznie inline to musiał byś użyć niszowego kompilatora.
A co do constexpr to nie zadziała bo kompilator nie zna wartości znaku w czasie kompilacji.

@edit: I mam jeszcze jedną uwagę do twojego kodu tzn. będzie on strasznie wolny (oczywiście nie zobaczysz tego w tak małym programie ale odradzam takich metod programowania). Jest to przykład jak nie programować, co prawda taki kod jest wygodny dla programisty, ale po co do prostego kodu stosować tak rozbudowane mechanizmy. Dla nas i kompilatora jest ważne jedynie wynik działania programu, a kompilator to wykorzystuje i wszystko co nie „materializuje” programu może zostać zoptymalizowane. Przez taki sposób odbierasz tą możliwość kompilatorowi ponieważ każde zewnętrzne wywołanie musi zostać potraktowane jako owa „materializacja” programu.

A co do
using namespace std;
 to już wiele razy pisałem na tym forum że „jest to zło w czystej postaci”.
P-145756
michal11
» 2016-03-08 21:35:31
Ale co masz dokładnie na myśli ?
P-145761
Kaikso
» 2016-03-08 21:38:28
W sprawie
constexpr
, powolności czy
using namespace std;
? Jeśli możesz to sprecyzuj pytanie.
P-145762
michal11
» 2016-03-08 21:52:02
Powolności.
P-145764
Kaikso
» 2016-03-08 22:31:01
Załóżmy że mamy taki program:

test.hpp
C/C++
#ifndef __TEST_HPP__
#define __TEST_HPP__

enum oper_e
{
    add,
    sub,
    mul,
    div,
    mod
}

int test( int a, int b, oper_e o );

#endif /* __TEST_HPP__ */

test.cpp
C/C++
#include "test.hpp"

int test( int a, int b, oper_e o )
{
    int r;
    switch( o )
    {
    case add: r = a + b; break;
    case sub: r = a - b; break;
    case mul: r = a * b; break;
    case div: r = a / b; break;
    case mod: r = a % b; break;
    }
   
    return r;
}

main.cpp
C/C++
#include "test.hpp"
#include <iostream>

int main()
{
    int a, b;
    std::cin >> a;
    std::cin >> b;
   
    std::cout << test( a, b, add ) << std::endl;
    std::cout << test( a, b, sub ) << std::endl;
    std::cout << test( a, b, mul ) << std::endl;
    std::cout << test( a, b, div ) << std::endl;
    std::cout << test( a, b, mod ) << std::endl;
   
    return 0;
}

Teraz pliki test.cpp i main.cpp kompilujemy osobno do pliku obiektowego.
W ten sposób kompilator podczas kompilacji main.cpp nie ma dostępu do wywoływanej funkcji więc nie może wykonać odpowiedniej optymalizacji bo funkcja test mogła by równie dobrze modyfikować zasoby zewnętrzne więc jest to owa „materializacja” się programu. Teraz dla prostej operacji dodawania, która mogła by być przetłumaczona na pojedynczą instrukcje procesora, zostanie wykonany szereg operacji najpierw przepisania argumentów do rejestrów, potem wywołania funkcji (zapisanie adresu powrotu i skoku), zapisanie ramki stosu na którą składa się kilka operacji, wykonania instrukcji warunkowych, wykonania działania, przywrócenie ramki stosu, powrotu z procedury (odczytanie adresu powrotu ze stosu i skok do niego). Zakłam że kompilator zoptymalizuje wewnątrz funkcje
test
.

Chodzi tu o to że używając bardzo rozbudowanych mechanizmów do prostych operacji kilkukrotnie może spowolnić czas działania danej części kodu. Bo przecież nigdy nie wiadomo co się kryje w zewnętrznym mechanizmie w nim mogą być kolejne wywołania i kolejne.

Sama biblioteka jest po to by ułatwić programistom życie i dla bardziej rozbudowanego kodu jest jak najbardziej wskazana, gdyż różnica w czasie działania może być nie znaczny, a czas na napisanie odpowiednich mechanizmów samemu może być nie opłacalne .

Pisząc własną bibliotekę C pod mój hobbistyczny OS przekonałem się ile naprawdę jest wewnętrznych zależności, a jest ich naprawdę wiele.

Dodam jeszcze że tak jak kompilator może zignorować
inline
 to równie dobrze może je dodać w szczególności przy funkcjach zadeklarowanych jako
static
. A używanie tych słów kluczowych pomaga kompilatorowi w decyzji.

Należy również pamiętać że kompilator nie zrobi wszystkiego za nas, a im bardziej mu pomożemy tym lepszy będzie efekt końcowy.
P-145770
michal11
» 2016-03-08 22:47:51
To co napisałeś kojarzy mi się ze zdaniem "Premature optimization is the root of all evil" - moim zdaniem takie rzeczy jak opisane przez ciebie kroki działania programu nie mają większego znaczenia dopóki właśnie nie zajdzie taka potrzeba i wtedy dopiera warto się zastanowić jak to rozwiązać. Równie dobrze wszystko można pisać w mainie żeby unikać skoków, przesuwania ramki stosu itp. rzeczy ale czy to ma sens ?
P-145771
1 « 2 » 3 4
Poprzednia strona Strona 2 z 4 Następna strona