Функции-члены такие же как передача ссылки на глобальную функцию? - PullRequest
3 голосов
/ 14 февраля 2011

Могу ли я быть уверен, что:

class foo {
  public:
  int x;
  void bar(int k) {
    x = k;
  }
};
foo o;
o.bar(5);

будет таким же, как:

class foo {
  public:
  int x;
};

void foobar(foo& f, int k) {
  f.x = k;
}

foo o;
foobar(o, 5);

Я знаю, что оба установят "x" в "k", но могу ли я бытьуверены, что они оба работают с одинаковой скоростью / генерируют одинаковый ассм?Может ли компилятор оптимизировать методы лучше?

Ответы [ 4 ]

3 голосов
/ 14 февраля 2011

Генерация ассемблера и сравнение (флаг -S для GCC).

2 голосов
/ 14 февраля 2011

В некоторых случаях он может иметь значение в сгенерированном ассемблерном коде, но (по крайней мере, обычно) не так много.

Например, компилятор Microsoft (обычно) будет использовать то, что они называют thiscall соглашением о вызовах для функций-членов, в этом случае указатель this передается в регистр ECX.По умолчанию для глобальных функций используется соглашение о вызовах cdecl, в котором все параметры передаются в стек.Однако также можно указать компилятору использовать соглашение о вызовах fastcall, в котором первые два параметра передаются в ECX и EDX соответственно (при условии, что вы передаете имитацию - this в качестве первого параметра,это заканчивается так же, как thiscall).

Несколько лет назад (например, 286, 386 таймфреймов), передача параметров в регистры вместо стека сэкономила немало времени.Теперь, когда большинство процессоров имеют по крайней мере несколько мегабайт встроенного кэша, большая часть этой разницы исчезла.

1 голос
/ 14 февраля 2011

Я знаю, что оба установят для "x" значение "k", но могу ли я быть уверен, что они оба работают с одинаковой скоростью / генерируют одинаковый asm?

Практически, вы можете быть уверены, что это не имеет значения. Если вы считаете, что это имеет значение, то профилируйте и сравните различия или посмотрите на вывод asm вашего компилятора.

Может ли компилятор оптимизировать методы лучше?

Обычно это невозможно. Особенно для коротких встроенных не виртуальных функций, как в вашем примере (вам нужно пометить foobar как встроенный, чтобы он был точно эквивалентен первому фрагменту кода), вызов функции в любом случае может просто исчезнуть.

0 голосов
/ 14 февраля 2011

В первом примере в таблице виртуальных функций для класса foo есть foo :: bar.Второго нет.Это делает его немного более эффективным.Поскольку foobar не является виртуальным, компилятор, вероятно, может сделать больше для оптимизации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...