Найкращий спосіб викликати функцію з різними аргументами, переданими за посиланням, коли вам потрібен лише один з цих аргументів

це просте питання:

Якщо мені потрібно називати такий спосіб, наприклад:

void getBounds(float &xmin, float &ymin, float &zmin,
             float &xmax, float &ymax, float &zmax)

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

Чи є спосіб зробити це? Скажімо, неправильний спосіб зробити те, що я хочу, буде щось на кшталт:

float xmax;
getBounds(nullptr, nullptr, nullptr, xmax, nullptr, nullptr);

Зараз я використовую змінні макета-сміття, але, можливо, існує інший спосіб.

Заздалегідь спасибі.

EDIT: Вибачте, я забув згадати, що не можу редагувати метод, це з сторонньої бібліотеки.

4
Я не впевнений, що деталі реалізації функції повинні впливати на спосіб його викликати. Я пропоную інкапсуляцію; покладіть функцію та дані разом на об'єкт.
додано Автор Peter Wood, джерело
std :: optional може бути прямим рішенням вашого питання. Однак я не розумію справжню потребу в цьому. У вас може виникнути питання дизайну. У цьому випадку, чому ви не впровадите функцію getXMax ?
додано Автор Matthieu Rouget, джерело
Припускаючи, що ви не можете змінити підпис дзвінка, можна створити одну манекенну змінну: float dummy; плавати xmin; getBounds (xmin, манекен, манекен, манекен, манекен, манекен); , які, однак, все ще можуть бути невибагливі, оскільки ця функція може використовувати внутрішні значення цих посилань для визначення, наприклад, xmin. Без будь-якої додаткової інформації щодо контракту getBounds передбачено, вам, імовірно, потрібно створити п'ять змінених змінних та передавати їх. (Тим не менш, ви можете приховати це в хорошій функції обгортки.)
додано Автор Philipp Matthias Schäfer, джерело
Я не думаю, що ви можете встановити nullptr, якщо ви приймаєте посилання
додано Автор Alexis, джерело
Ваше ім'я невірно: аргументи не передаються за значенням, вони передаються за посиланням (для написання). Я запропонував редагувати.
додано Автор gx_, джерело
Я думаю, ви можете надіслати 0 замість nulls
додано Автор user2140173, джерело
Я забув згадати, що не можу редагувати цей метод. Я роблю "манекен", я запитував, чи існує інше рішення.
додано Автор AlexTemina, джерело

6 Відповіді

Ви можете змінити getBounds чи ні? Якщо можна, і розрахунок кожен із цих цін є дорогим, він може варто змінити його щоб передати покажчики, і лише зробити відповідний розрахунок, якщо покажчик не нульовий. В іншому випадку вам потрібно буде передати значення l (змінної) для кожного. І теоретично, якщо ви пройдете те ж саме змінна до більш ніж одного аргументу, ви можете отримати це невизначеною поведінка в функції (скажімо, оскільки функція починається з щось уздовж рядків xmin = ymin = 0.0; ).

Нарешті, якщо обчислення кожного значення дорожче, а Функція пропускає його, якщо він отримує нульовий покажчик, створюючи і проходження додаткових змінних навряд чи вплине на це продуктивність

2
додано
Я не можу змінити getBounds, це, безумовно, найкраще рішення. Хоча я можу створити обгортку і маскувати цей метод.
додано Автор AlexTemina, джерело

Щось на зразок:

float dummy;
float xmax;

getBounds(dummy, dummy, dummy, xmax, dummy, dummy);

Це створить лише одну змінну в стекі, тим самим заощаджуючи простір, - створення більшості з них не матиме жодного побічного ефекту, крім прийняття ще 4 байтів кожен [припускаючи, що "нормальний" розмір плаває, стандарт не вказує точний розмір флоту ] - це займає таку ж кількість часу, щоб створити одну або п'ять (або сто) неініціалізованих змінних на основі стеку.

Використання вказівників дозволить вам передати nullptr , однак також додасть додаткову перевірку в getBounds , так що

void getBounds(....)
{
    xmin = the_getXmin_function();
    ...
}

стає:

void getBounds(....)
{
    if (xmin != nullptr)
        *xmin = the_getXmin_function();
    ...
}

Припускаючи, що the_getXmin_function тривіальний, це призведе до сповільнення коду. Якщо функція складна, то наявність параметра if і "Я не хочу цього" допоможе виконати трохи.

1
додано
@MatsPetersson Питання полягає в тому, чи є аргументи вихідними (оскільки вони є неконстультативними посиланнями, ми можемо припустити, що їх немає). Але навіть якщо вони суто виходять, якщо getBounds робить щось на кшталт xmax = (xmin = something) + 1 , а xmax і xmin стосуються того самого об'єкта, у вас є невизначена поведінка. (Особисто я б стверджував, що ви повинні мати змогу передавати ту саму змінну, якщо це не буде іншим документом. Фактично, я підозрюю, що зворотній зв'язок ближче до реальності.)
додано Автор James Kanze, джерело
Погана реалізація: так, я згоден. Але якщо ви коли-небудь працювали, скажіть, Windows API, то ви дізнаєтеся про погану реалізацію!
додано Автор Bathsheba, джерело
Матс Петеррссон; це може бути небезпечно: ви не знаєте, як getBounds вживає змінні: їх можна використовувати на проміжних етапах. Так, ви могли читати вихідний код, але цей вихідний код може змінюватися в майбутніх версіях.
додано Автор Bathsheba, джерело
Так, це можливо. Те, що це буде досить поганою реалізацією функції, якщо вона використовує вхідні параметри для внутрішніх розрахунків - якщо нічого, бо це повільніше.
додано Автор Mats Petersson, джерело
У цьому випадку, чому безпосередньо не виставляти світові the_getXmin_function() і подібні функції?
додано Автор Matthieu Rouget, джерело

Підтвердження Матса Петерссона: ви не можете пройти nullptr, оскільки для функції потрібні посилання.

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

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

0
додано
Хороший пункт Мати; Я редагував
додано Автор Bathsheba, джерело
Технічно ви не можете передати nullptr як те, що містить посилання.
додано Автор Mats Petersson, джерело

Якщо ви можете переписати getBounds і можете використовувати C ++ 11, розгляньте можливість використання кортежу, зв'язувати та ігнорувати:

std::tuple getBounds()
{
  std::tuple r;
  :
  std::get<3>(r) = ...;
  :
  return(r);
}
:
float xmax;
std::tie(std::ignore, std::ignore, std::ignore, xmax, std::ignore, std::ignore> = getBounds();

--EDIT--

Оскільки ви не можете змінити це, ви можете перевантажити його. Параметрична версія буде просто обернути навколо оригіналу, упакувати все у кортежі і повернути його.

0
додано

Ви не можете відправити nullptr, якщо функція чекає посилання

Але якщо ви зміните свій підпис функції для покажчика, ви можете перейти на щось подібне: void getBounds (float * xmax, float * xmin = nullptr, float * ymin = nullptr, float * zmin = nullptr, float * ymax = nullptr, float * zmax = nullptr) {}

and call it: getBounds( &xmax); but then you must check in your function if the variable is nullptr or no

але, як сказано в коментарях, він буде працювати тільки в одному випадку

0
додано
Ваше рішення працює лише для xmax . І розміщення xmax перед xmin , а ymin перед ymax дійсно є поганою ідеєю.
додано Автор Matthieu Rouget, джерело
Я не можу змінити функцію. Я наклав приклад nullptr, щоб показати вам, що я хочу, я знаю, що це абсолютно невірно;)
додано Автор AlexTemina, джерело

Якщо ви написали цей метод, просто змініть підпис функції на

void getBounds( float*, float*, float*, float*, float*, float* )

так що ви можете передавати nullptrs , якщо хочете ігнорувати параметр. В іншому випадку ви можете написати функцію обгортки.

void getBounds( float*a, float*b, float*c, float*d, float*e, float*f )
{
    float dummy;
    getBounds( 
        a ? *a : dummy, 
        b ? *b : dummy, 
        c ? *c : dummy, 
        d ? *d : dummy, 
        e ? *e : dummy, 
        f ? *f : dummy );
}

Якщо ваша ситуація не відбувається регулярно, іншим способом вирішення цієї проблеми може стати написання

float xmax;//in outer scope
{
    float dummy;//in inner scope. Will be thrown away afterwards
    getBounds( dummy, dummy, dummy, xmax, dummy, dummy );
}

тому ви не переповнюєте вашу сферу застосування.

Я б вважав за краще перший варіант.

0
додано
Дякую. Я змінив його.
додано Автор Ralph Tandetzky, джерело
Ну, оскільки моя пропозиція редагування була відхилена (...) я прокоментую: ваша перевантаження параметрів покажчика в даний момент невірна, і не буде компілювати, шість виразів, таких як a? * a: і манекен має бути як a? * a: dummy ( & dummy -> dummy ). Редагувати: ви просто редагували себе: p (ласкаво просимо)
додано Автор gx_, джерело
IT KPI C/С++ новым годом
IT KPI C/С++ новым годом
747 учасників

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