2015-09-09 5 views
3

Я новичок в программировании, и я изучаю язык программирования C++, используя книгу: Принципы программирования и практика с использованием C++. Я здесь сегодня, потому что в конце 8-й главе, автор сосредотачивается на функциях и предлагает упражнения, чтобы пригласить ученика думать о лучшем решении проблемы:Возвращаемые значения из функции: reference vs struct

Написать функцию, которая находит наименьшее и самый большой элемент векторного аргумента, а также вычисляет среднее и медианное. Не используйте глобальные переменные. Либо верните struct, содержащий результаты, либо передайте их обратно через ссылочные аргументы. Кто из двух возвращал несколько значений, вы предпочитаете и почему?

Теперь, как правило, я бы не определял одну функцию для выполнения нескольких действий, но в этом случае мне нужно создать только одну функцию и подумать о том, как вернуть несколько значений. Мой первый подход заключается в создании функции, которая принимает ссылочные аргументы так:

void my_func(
    vector<double>& numbers, 
    double& min, 
    double& max, 
    double& mean, 
    double& median 
); 

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

+0

Вы не возвращаете несколько значений из функции, это невозможно. Вместо этого вы возвращаете экземпляр * one * structure, содержащий несколько членов (например, члены, такие как 'min',' max' и т. Д.). –

+0

Используйте [encapsulation] (https://en.wikipedia.org/wiki/Encapsulation_ (computer_programming)), когда это полезно и возможно. Здесь это возможно и полезно, и поэтому вы должны использовать здесь структуру (например, статистику), предложенную в ответах. – HelloWorld

+1

Если вы используете C++ 11, вы можете взглянуть на [std :: tuple] (http://en.cppreference.com/w/cpp/utility/tuple) –

ответ

5

Использование struct этой проблемы проста: определить struct для типа возвращаемого значения, и использовать его, как это:

struct stats { 
    double min; 
    double max; 
    double mean; 
    double median; 
}; 
stats my_func(vector<double>& numbers) { 
    stats res; 
    ... 
    res.min = ... 
    res.max = ... 
    res.mean = ... 
    res.median = ... 
    return res; 
} 

Компромисс здесь является то, что в обмен на имеющий более простую функцию подписи, пользователям вашей функции необходимо извлечь элементы, которые они хотят по одному.

Но как быть, если структура действительно сложна и стоимость копирования становится слишком дорогой?

Требуется структура экстремальных размеров для копирования, чтобы стать слишком дорогостоящей по сравнению с процессорным временем вашей полезной нагрузки. Кроме того, C++ оптимизатор сокращает затраты на копирование с использованием copy elision и return value optimization стратегии, когда вы это делаете:

stats s = my_func(numbers); 

Когда struct становится настолько велико, что вы не хотите, чтобы скопировать его, объединить эти два подхода, как это:

void my_func(vector<double>& numbers, stats& res); 
+0

@PoojaNilangekar Спасибо, это было хорошим редактированием. К сожалению, он автоматически отклонился, потому что я сам редактировал ответ. Спасибо, что выбрали эту ошибку для копирования-вставки! – dasblinkenlight

+0

Из основ, которые я узнал, я знаю, когда функция возвращает значение в вашем примере, создается копия return_value. Но как быть, если структура действительно сложна и стоимость копирования становится слишком дорогой? –

+1

@pieroborrelli С семантикой и копией шансов на копирование хорошо, вы фактически не сделаете копию. Особенно, если вы инициализируете переменную из функции return. – NathanOliver

0

Объявить struct

т.е.

struct stats { 
    double min; 
    double max; 
    double mean; 
    double median; 
}; 

Тогда

stats my_func(vector<double>& numbers); 

функция будет выглядеть следующим образом

stats my_func(vector<double>& numbers) { 
    stats return_value; 

    // Fill in the structure 

    return return_value; 
} 
0

Ну вы просто вернуть структуры.

struct res { 
    double min; 
    double max; 
    double mean; 
    double median; 
}; 

res my_func(vector<double>& numbers) { 
    res result; 
    // do stuff, put result in in result.min etc 

    return result; 
} 

Другой может быть сделано аналогичным образом:

void my_func(vector<double>& numbers, 
      res& result) 
{ 
    // the same code except no return value 

    return; 
} 

Теперь вопрос в вашей задаче (я не буду отвечать - потому что это вопрос, что вы предпочитаете) Я хотел бы чтобы указать, что такое техническая разница.

При возвращении на структуру это означает, что вы, возможно, создать временную копию result структуры (это также может привести к двум объектам res один для вызывающего абонента и один для my_func работать). В то время как другой подход означает, что вы переходите к функции, по существу адресует, где поставить результат. При «хорошей» реализации вы можете получить тот же код.

+0

С семантикой и копией шансов на копирование хорошо, вы фактически не сделаете копию. Особенно, если вы инициализируете переменную из функции return. – NathanOliver

+0

Вероятность этого изменилась, я изменил форму «возможно» на «возможно», чтобы указать, что в наши дни это менее вероятно. – skyking

Смежные вопросы