Різниця між змінних всередині функції та змінних, що функціонують як аргументи в C ++

Моє запитання надходить з Правильний спосіб проектування функції з інформацією про налагодження в C ++ та без неї . Я хочу порівняти ефективність наступних функцій:

Функція 1

bool my_func1(int arg1, int &output, std::vector &intermediate_vec);
  {
    //do something
  }

Коли я використовую цю функцію, я називаю його наступним чином:

int arg;
int output;
std::vector intermediate_vec;
my_func1(arg,output,intermediate_vec);

Функція 2

  bool my_func2(int arg1, int &output);
  {

    std::vector intermediate_vec
    return my_func1(arg1, output, intermediate_vec);
  }

Коли я використовую цю функцію, я називаю його наступним чином:

int arg;
int output;
my_func2(arg,output);

Моє питання: чи є ці дві функції однією і тією ж ефективністю?

1
Якщо ви визначите його в заголовку, my_func2 , імовірно, буде вбудованим і призведе до того самого коду.
додано Автор KillianDS, джерело
Ефективність, мабуть, неважливо тим, що це часто робиться, коли ви виставляєте безпечний інтерфейс для користувача, але закриваєте приватний метод позаду сцен, оскільки потрібно сховати vector . Тому не відвертайтеся від нього. Вставте або видаліть BST.
додано Автор ChiefTwoPencils, джерело

6 Відповіді

Це одне з тих питань, де деталі потрібно точно відповісти.

Має бути дуже мало відмінностей, особливо, якщо компілятор вбудовує в себе інтерфейс func1 або func2 , щоб уникнути зайвих накладних витрат (тобто функції оголошуються таким чином, що вони можуть "бачити" компілятор з викличного коду).

Єдиний раз, коли існує більша різниця, якщо ви зможете уникнути побудови/руйнування intermediate_vec - наприклад, ви повторно використовуєте той самий цикл (але, швидше за все, ви "скинете" вектор у цьому випадку, що є основною частиною руйнування вектора).

Наскільки велика різниця, як частка від загального часу, залежить від того, що саме робить do something в func1 .

Однак, як і всі питання ефективності, варто порівняльний аналіз продуктивності. Переконайтеся, що ви скомпілюєте його з рівнем оптимізації вашого фактичного коду.

2
додано
При "перезавантаженні" вектора я вважаю, що ви маєте називати clear на нього. Виклик clear не зменшує пропускну здатність і не звільняє жодну пам'ять, тому наступного разу вам не потрібно перерозподіляти. Якщо конструктор та деструктор містяться елементів є значними, додатковий розподіл, мабуть, не матиме значення. Якщо вони не є, це може (але це трохи залежить від того, як компілятор оптимізує).
додано Автор James Kanze, джерело
Можливо, я створив штучний приклад, де він набагато гірший, принаймні для деяких компіляторів. Я сумніваюся, такі випадки фактично зустрічаються в реальному коді, однак. Зрештою, у вашому останньому абзаці сказано все це (до якого я хотів би додати: не турбуйтеся , якщо у вас дійсно не вистачає проблем із продуктивністю).
додано Автор James Kanze, джерело
Так, зателефонувавши clear або виконавши щось із таким ефектом (наприклад, заповнення вектора з нулем або інше, оскільки він є вектором int , деструктор не є таким . Ось, мабуть, трохи "гірше" викликати деструктор векторів, ніж clear .
додано Автор Mats Petersson, джерело

Питання дійсно досить нерозумно; це дійсно залежить від ви використовуєте intermediate_vec . Якщо це частина інтерфейс, ви повинні зробити це аргументом і документувати його попередні та пост-умови. Якщо він не є частиною інтерфейсу, то, перетворюючи аргумент на нього, виявляє внутрішні функції які не повинні піддаватися. Ефективність (крім програміста ефективність) не входить в неї.

Крім того, єдиний спосіб порівняння ефективності (принаймні в такі випадки), це вимірювати.

І, нарешті, якщо ви дзвоните за функцією в суворому порядку, часто виконаний цикл, а профіліст показує, що будівництво intermediate_vec (у версії 2) викликає значні затримки, ви можете отримати, використовуючи першу версію і переміщаючи фактичну вектор поза циклом; вектор, ймовірно, досягне його максимальна потужність досить швидко, а після цього буде немає подальших динамічних розподілів. Але така зміна є щось, що потрібно робити лише у випадках абсолютної необхідність, коли програма не досить швидко, а також Profiler показує, що розподіл при створенні вектора є значна причина для цього. І я хотів би підкреслити ти може ; багато що ще залежить від того, як компілятор оптимізує, і як реалізовано std :: vector .

1
додано

Ви нічого не можете сказати про ефективність функцій тільки з його підпису. Я можу написати найшвидкісні та найповільніші функції, які ви можете собі уявити за допомогою однієї з цих підписів.

У другому варіанті ви додасте третій параметр до функції. Вам потрібен цей параметр? Якщо вам це потрібно, скористайтеся цим варіантом. Якщо це не так, скористайтеся першим.

1
додано
Я просто надаю дві функції для користувачів, для яких може знадобитися інший підпис для однієї функції.
додано Автор feelfree, джерело
Я надаю дві функції. Один з меншими аргументами для реального застосування, а один з більшою кількістю аргументів використовується для налагодження. Я задаю це питання просто з цікавості.
додано Автор feelfree, джерело
@feelfree Якщо вам потрібні обидва вони, то - чому ви дбаєте, який з них найшвидший?
додано Автор Daniel Daranas, джерело

Виміряйте час роботи процесора для реалістичного вимірювання

0
додано

Оскільки ви передаєте вектор як посилання (замість створення тимчасових копій), будь-яка різниця продуктивності була б незначною (компілятор може навіть вставити його в щось еквівалентне, якщо ні, ви можете потрапити в деяку частину кадру стека).

Це також залежить від того, що насправді робить щось , і як ці функції також називаються (наприклад, чи є це певною щільністю циклу).

Краще пройти і подивитися.

0
додано

Поведінка оптимізованих функцій часто дуже непередбачувана. Після того, як всі ваші функції можуть бути введені і показати точно ті ж характеристики продуктивності. Вони можуть бути не вбудованими, або жодна оптимізація може вийти з ладу в будь-якому випадку, і в будь-якому випадку може бути гірша продуктивність. Єдиний спосіб серйозно підрахувати такі речі, як це виміряти продуктивність за допомогою надійного профілератора в різних налаштуваннях.

0
додано
IT KPI C/С++ новым годом
IT KPI C/С++ новым годом
747 учасників

Чат обсуждения С/С++. - Вопросы "напишите за меня лабу" - это оффтоп. - Оффтоп, флуд, оскорбления и вбросы здесь не приняты. - За нарушение - предупреждение или mute на неделю. - За спам и рекламу - ban. Все чаты IT KPI: https://t.me/itkpi/1147