funkcja inline

0
#include "../require.h"
#include <iostream>
using namespace std;

template<class T>
class Array {
  enum { size = 100 };
  T A[size];
public:
  T& operator[](int index) {
    require(index >= 0 && index < size,
      "Index out of range");
    return A[index];
  }
};

int main() {
  Array<int> ia;
  Array<float> fa;
  for(int i = 0; i < 20; i++) {
    ia[i] = i * i;
    fa[i] = float(i) * 1.414;
  }
  for(int j = 0; j < 20; j++)
    cout << j << ": " << ia[j]
         << ", " << fa[j] << endl;
} ///:~

Z thinking in C++

Zwróć uwagę, że w przypadku gdy indeks jest niepoprawny do wydrukowania komunikatu jest używana funkcja require(). Ponieważ operator jest funkcja inline można używać takie sposobu w celu upewnienia się, że nie następuje naruszenie granic, a z gotowego kodu usunąć funkcję require()

a)Dlaczego ten operator jest inline, a inne nie są, jaki jest tego powód?
b) w sumie, wyszło też drugie pytanie, niektóre spośród operatorów muszą być definiowane w klasie, a niektóre poza nią. Dlaczego? Czy ma to związek z tą inlinowosćią, np. opertora [].
2) Do cytatu:
Dlaczego inlinowość funkcji nam to umożliwia. Czegoś nie wiem? Ja na funkcje inline patrzę tak:
Jeżeli funkcje są małe i nie ma sensu skakać w inne miejsce w pamięci to użyj inline. To myślenie ma jakieś defekty?

0

Po zinline'owaniu funkcji kompilator może odpalić swoje optymalizacje jeszcze raz, np usuwanie nadmiarowych ifów (w sensie np ty coś testujesz w miejscu wywołania operatora, a operator w środku testuje znów to samo). Funkcja która nie jest zinline'owana jest pewnego rodzaju black-boxem i kompilator nie jest w stanie wiele zrobić z wywołaniem.

0

ok. Czyli kompilator widząc przeciążanie [] sam go robi inline? Rozumiem, że jeżeli funkcja jest inline to kompilator nabiera śmiałości do optymalizacji. Tylko dlaczego?
Dobrze, ale dlaczego przeciążenie operatora [] jest akurat inline. Rozumiem, że ze względu na optymalizację. Ale jaką? Bo jest to przecież znane.

1

Generalnie, jeżeli nie używasz LTO to kompilator zinline'ować może tylko funkcje w aktualnej jednostce kompilacji (tzn plik .c/ .cpp + wszystkie dołączone pliki nagłówkowe). Wrzucając implementację operatora do deklaracji klasy sprawiasz, że ta implementacja jest widoczna wszędzie, a co za tym idzie zewsząd można ją zinline'ować.

Rozumiem, że jeżeli funkcja jest inline to kompilator nabiera śmiałości do optymalizacji. Tylko dlaczego?

Pfff. Śmiałości :P Nie chodzi o żadną śmiałość. Funkcja niezinline'owana jest w dużej mierze black-boxem - kompilatorowi dużo trudniej robić optymalizacje które przebijają się przez wywołania funkcji. Trudniej, bo przecież z tej niezinline'owanej funkcji można korzystać też z innych miejsc, więc ta funkcja musi zachować poprawność i przez to sprawdzać wszystkie niezmienniki zawarte w kodzie źródłowym.
Inline'ing to usunięcie wywołania funkcji, wklejenie ciała metody wywoływanej do funkcji wywołującej. Dzięki temu cały kod jest efektywnie w jednej funkcji, przez co łatwiej jest optymalizować, bo wklejone ciało funkcji jest niezależnym bytem.

0

dobrze. To mi wyjaśniłeś, ale dalej nie odpowiedziałeś, co operator [] ma w sobie takiego szczególnego?

1

A ma? Próbowałeś go definiować w osobnym pliku .c/ .cpp?

W sensie w definicji klasy zrób:

T& operator[](int index);

A w osobnym pliku .cpp zrób:

T& Array::operator[](int index) {
ciałolalalal;
}

Czy cóś w ten deseń.

Stawiam że ta inline'owość wynika tylko i wyłącznie z tego, że zdefiniowałeś operator w definicji klasy, a nie w osobnej jednostce komplacji.
Chociaż mogę się mylić, bo w C++ koduję tylko hobbystycznie i zgłębianie tego języka nie sprawia mi szczególnej przyjemności :P

1 użytkowników online, w tym zalogowanych: 0, gości: 1